diff --git a/projects/base_system/block_design.tcl b/projects/base_system/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..80ab85eaa9c8662cb1c21208b16e9936985567f9
--- /dev/null
+++ b/projects/base_system/block_design.tcl
@@ -0,0 +1,30 @@
+# Create clk_wiz
+cell xilinx.com:ip:clk_wiz pll_0 {
+  PRIMITIVE PLL
+  PRIM_IN_FREQ.VALUE_SRC USER
+  PRIM_IN_FREQ 125.0
+  PRIM_SOURCE Differential_clock_capable_pin
+  CLKOUT1_USED true
+  CLKOUT1_REQUESTED_OUT_FREQ 125.0
+  USE_RESET false
+} {
+  clk_in1_p adc_clk_p_i
+  clk_in1_n adc_clk_n_i
+}
+
+# Create processing_system7
+cell xilinx.com:ip:processing_system7 ps_0 {
+  PCW_IMPORT_BOARD_PRESET cfg/red_pitaya.xml
+  PCW_USE_S_AXI_ACP 1
+  PCW_USE_DEFAULT_ACP_USER_VAL 1
+} {
+  M_AXI_GP0_ACLK pll_0/clk_out1
+  S_AXI_ACP_ACLK pll_0/clk_out1
+}
+
+# Create all required interconnections
+apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config {
+  make_external {FIXED_IO, DDR}
+  Master Disable
+  Slave Disable
+} [get_bd_cells ps_0]
diff --git a/projects/cfg_test/block_design.tcl b/projects/cfg_test/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..51fa542cdcd254c4f1437d40cdaa8b958eb54506
--- /dev/null
+++ b/projects/cfg_test/block_design.tcl
@@ -0,0 +1,48 @@
+source projects/base_system/block_design.tcl
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_0
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0 {} {
+  ext_reset_in const_0/dout
+}
+
+# Create c_counter_binary
+cell xilinx.com:ip:c_counter_binary cntr_0 {
+  Output_Width 32
+} {
+  CLK pll_0/clk_out1
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_0 {
+  DIN_FROM 26 DIN_TO 26
+} {
+  din cntr_0/Q
+}
+
+# Create axi_cfg_register
+cell labdpr:user:axi_cfg_register cfg_0 {
+  CFG_DATA_WIDTH 1024
+  AXI_ADDR_WIDTH 7
+  AXI_DATA_WIDTH 32
+}
+
+addr 0x40001000 4K cfg_0/S_AXI /ps_0/M_AXI_GP0
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_1 {
+  DIN_WIDTH 1024 DIN_FROM 134 DIN_TO 128
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlconcat
+cell xilinx.com:ip:xlconcat concat_0 {
+  IN1_WIDTH 7
+} {
+  In0 slice_0/dout
+  In1 slice_1/dout
+  dout led_o
+}
diff --git a/projects/gpio_led_test/block_design.tcl b/projects/gpio_led_test/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..06376a358f82839f9418f04521637ea84eced20c
--- /dev/null
+++ b/projects/gpio_led_test/block_design.tcl
@@ -0,0 +1,56 @@
+source projects/base_system/block_design.tcl
+
+#Enable interrupts
+set_property -dict [list CONFIG.PCW_USE_FABRIC_INTERRUPT {1} CONFIG.PCW_IRQ_F2P_INTR {1}] [get_bd_cells ps_0]
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_0
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0 {} {
+  ext_reset_in const_0/dout
+}
+
+# Create axis_rp_adc
+cell labdpr:user:axis_rp_adc adc_0 {
+  ADC_DATA_WIDTH 14
+} {
+  aclk pll_0/clk_out1
+  adc_dat_a adc_dat_a_i
+  adc_dat_b adc_dat_b_i
+  adc_csn adc_csn_o
+}
+
+# Create c_counter_binary
+cell xilinx.com:ip:c_counter_binary cntr_0 {
+  Output_Width 32
+} {
+  CLK pll_0/clk_out1
+}
+
+# Create xlslice
+cell xilinx.com:ip:xlslice slice_0 {
+  DIN_WIDTH 32 DIN_FROM 26 DIN_TO 26 DOUT_WIDTH 1
+} {
+  Din cntr_0/Q
+}
+
+# Create GPIO core
+cell xilinx.com:ip:axi_gpio axi_gpio_0 {
+   C_GPIO_WIDTH 8
+  C_GPIO2_WIDTH 1
+  C_ALL_OUTPUTS 1
+  C_IS_DUAL 1 
+  C_ALL_INPUTS 0 
+  C_ALL_INPUTS_2 1
+  C_INTERRUPT_PRESENT 1 
+  C_ALL_OUTPUTS 1
+} {
+  s_axi_aclk pll_0/clk_out1
+  s_axi_aresetn rst_0/peripheral_aresetn
+  ip2intc_irpt ps_0/IRQ_F2P
+  gpio_io_o led_o
+  gpio2_io_i slice_0/Dout
+}
+
+addr 0x40000000 4K axi_gpio_0/S_AXI /ps_0/M_AXI_GP0
diff --git a/projects/gpio_led_test/gpio_led_test.c b/projects/gpio_led_test/gpio_led_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..bd79c4a74b5a5fe7c0bf50834880205f6d4419c3
--- /dev/null
+++ b/projects/gpio_led_test/gpio_led_test.c
@@ -0,0 +1,575 @@
+/* basic_design_zynq_hw_exerciser.c
+ *
+ * This program demonstrates the basic capabilities of a Zynq platform
+ * communicating with two axi_gpio peripherals (from the IP catalog) that
+ * are implemented as hardware in the PL.
+ *
+ * NOTE: THE GPIO THAT IS CONTAINED IN THE PS IS NOT BEING USED
+ *
+ * One of the GPIO's is configured as an 8 bit output driving 8 LED's.
+ * The other GPIO is configured as a three input device being driven
+ * from push buttons.
+ *
+ * The program functions in a forever loop, monitoring the input push
+ * buttons.  The three buttons are UP, DOWN, and STOP that directly
+ * control the a binary counting pattern on the LED's.
+ *
+ * This application is written to either, use the Standalone library
+ * or be compiled as a Linux application. Either flow is supported in
+ * the SDK programming development. The default compilation is using
+ * the Standalone library. To compile this application as a Linux
+ * application, add to the properties of the associated application
+ * project, a #define of a symbol named "LINUX_APP". Select properties and
+ * C/C++ Build => Settings => ARM Linux gcc compiler => Symbols,
+ * adding a -D LINUX_APP to the gcc compiler tool command line.
+ *
+ * The hardware (axi_gpio) physical device pinout in the PL may vary
+ * with the target evaluation board being used. This variation is
+ * typically manifested in the constraints file which determines
+ * device pin locations for the actual pin numbers used for the LED's
+ * and pushbuttons. Other variations in the hardware may be needed to
+ * accommodate the fact that varying numbers of pushbutton inputs or
+ * LED output actually exist.
+ * 
+ * The goal is that  this application can be targeted to multiple
+ * hardware Zynq platforms (or configurations) either as a Standalone
+ * or Linux application.
+ *
+ * THE FOLLOWING HARDWARE PLATFORMS ARE DEFINED
+ * ZC702 BOARD
+ * LED's - Eight LED's, DS15-DS22, located towards the center of the
+ *         board from the SD card slot
+ * Push Buttons - Only two buttons are use, located adjacent to the LED's
+ *         UP - SW7
+ *         DOWN - SW5
+ *         STOP - Pressing both, SW5 and SW7, at the same time provides a STOP
+ *         (Due to a lack of pushbuttons accessible by PL pins, hardware
+ *          in the PL was added to emulate a third button)
+ *
+ * ZC702 BOARD WITH CE (Customer Education) FMC CARD IN FMC1 SLOT
+ * LED's - Eight LED's, LD0-LD7, located between slide switches and LCD display
+ * Push Buttons - Rosetta buttons located on CE FMC card,
+ *         UP - BTN3 - West
+ *         DOWN - BTN0 - Center
+ *         STOP - BTN1 - East
+ *
+ * ******************************************************************************************************************
+ *
+ * 
+ *   basic_design_exerciser
+ *   Ver.:  1.0    6/1/2012 WK/LR
+ *
+ *   This code generates an LED pattern for the 8 bit LED array present on the ZC702 board. It must have
+ *   one of several symbols defined: 
+ *      hardware_test   - infinite loop,         long delays for LEDs so user can visually recognize what is happening, uses standalone drivers
+ *      profiler_test   - finite loop for gprof, short delays so profiler doesn't report all the activity being in the wait_loop function, uses standalone drivers
+ *      CSP_test        - infinite loop,         short delays so multiple datum can be captured with the Analyzer, uses standalone drivers
+ *      LINUX_APP       - infinite loop,         long delays for LEDs so user can visually recogize what is happening, uses Linux drivers
+ *
+ * ******************************************************************************************************************
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+// Stuff needed for Linux DEVMEM access
+#define MAP_SIZE 4096UL
+#define MAP_MASK (MAP_SIZE - 1)
+#define TRUE 1
+#define FALSE 1
+typedef int u32;	                              // add this compatibility for int's between Linux and Standalone
+
+// Linux pointers to GPIO's in PL hardware
+void *mapped_led_dev_base;		// Address of LED GPIO
+void *mapped_button_dev_base;	// Address of Push Button GPIO
+void *mapped_base;				// Address of device memory window, it is global for visibility in main to unmount device memory
+int memfd; 						// device memory handle for Linux device to memory mapping, it is global for visibility in main to unmount device memory
+
+// Linux application needs gpio base address and register offsets, Standalone application gets it from xparameters.h
+#define GPIO_BUTTON_BASE_ADDRESS	0x41240000
+#define GPIO_LED_BASE_ADDRESS    	0x40000000
+#define GPIO_DATA_OFFSET     		  0x0000
+#define GPIO_DIRECTION_OFFSET    	0x0004
+
+// access the serial output
+#define print printf
+
+// constants
+#define LED_DELAY_NORMAL   5000000
+#define LED_DELAY_PROFILE        2
+#define BUTTON_CHANNEL           1
+#define LED_CHANNEL              1
+#define ALL_OUTPUTS              0
+#define ALL_INPUTS      0xffffffff
+
+
+// function prototypes  (functions defined in this file after the main)
+void *Linux_GPIO_initialize(int gpio_base_address, int direction, int first_call);
+
+// for the hardware exerciser...
+void    hardware_exerciser();                                     // name of routine follows common 'C' language convention
+#define PI (double)3.141592653                                    // approximation of PI
+void    do_sine_sample(int sample);                               // takes sample and calls other routines to get results to LEDs, serial port
+void    doBarGraph(int value, int style);                         // name of routine follows common Java language convention (legal for C)
+void    driveBarGraph(int value);                                 // actually selects which LEDs are active and makes peripheral call
+#define CYLON  1
+#define BAR    2
+#define BINARY 3
+double  sine(double angle_in_radians);
+double  factorial(int final_term);
+char   *itoa(int value, char *string, int radix);
+char   *strcat (char *destination, const char *source);
+void    delay_loop(long int delay_count);
+int     buttons_get_state(void);
+void    LEDs_driver(int pattern);
+
+int   LED_delay_max;                                              // maximum value to delay to for the LED wait loop
+
+/*
+ *  ***********************************************************
+ */
+int main() {
+
+	// local variable
+	int mode = 0;                                                 // used to check that one of the environment variables used
+
+	// let the user know that we're starting
+	print("---basic_design_zynq Exerciser---\n\r");
+
+	//***** initialize the GPIOs *****
+	// For Linux access memory mapped GPIO without kernel driver and initialize.
+	// The function returns a pointer address to the associated GPIO and sets the GPIO direction
+	mapped_led_dev_base = Linux_GPIO_initialize(GPIO_LED_BASE_ADDRESS, ALL_OUTPUTS, TRUE);
+	mapped_button_dev_base = Linux_GPIO_initialize(GPIO_BUTTON_BASE_ADDRESS, ALL_INPUTS, FALSE);
+
+
+	// determine the use of this software - are we exercising the hardware or doing the profiling exercise?
+#ifdef hardware_test
+	LED_delay_max = LED_DELAY_NORMAL;
+	print("running the hardware test...\n\r");
+	mode = 1;
+#endif
+
+#ifdef profiler_test
+	LED_delay_max = LED_DELAY_PROFILE;
+	print("running the profiler code...\n\r");
+	mode = 2;
+#endif
+
+#ifdef CSP_test
+	LED_delay_max = LED_DELAY_PROFILE;
+	print("running the CSP analyzer code...\n\r");
+	mode = 3;
+#endif
+
+	LED_delay_max = LED_DELAY_NORMAL;
+	print("running the Linux app...\n\r");
+	mode = 4;
+
+	// check to see that one or the other mode was selected, otherwise warn the user and abort
+	if (mode != 0) {
+		hardware_exerciser();                                // read switches, detect changes, increment/decrement counter, display count on LEDs...
+	} else {
+		print("you must set the symbol \"hardware_test\", \"profiler_test\", \"CSP_test\", or \"LINUX_APP\" in the compiler settings!\n\r");
+	}
+
+	print("---Exiting main---\n\r");							// never reached...
+
+	// unmap the memory used for the GPIO device before exiting
+	// Linux only, but will never be reached
+	// It is a good programming practice to always release the memory space the device was accessing
+	// Since the Standalone drivers can always access memory, this sort of functionality is not needed
+	if (munmap(mapped_base, MAP_SIZE) == -1) {
+		printf("Can't unmap memory from user space.\n");
+		exit(0);
+	}
+	printf("Memory Unmapped\n");
+	close(memfd);
+
+	return 0;
+}
+
+
+
+/*
+ * ************** Hardware Exerciser Code *************************
+ */
+#define UP    0
+#define LEFT  0
+#define DOWN  1
+#define RIGHT 1
+#define STOP  2
+
+#define ONE_PERIOD 128
+#define AMPLITUDE  256
+#define ABS(a) (((a) < 0) ? -(a) : (a))
+
+/*
+ * ****************************************************************************************************
+ *    HARDWARE EXERCISER CODE 
+ * ****************************************************************************************************
+ */
+
+void hardware_exerciser() {
+	// local variables
+	u32 last_button_state = 0;
+	u32 current_button_state = 0;
+	u32 button_difference = 0;
+	int count_direction = UP;
+	int sample = 0;
+	int keep_running = 1;
+	int profile_iteration_count = 500000;                        // used only in profile mode
+
+	// deliberate infinite loop
+	while (keep_running) {
+		// read current switch configuration
+		current_button_state = buttons_get_state();
+		button_difference = (current_button_state ^ last_button_state) & current_button_state; // detect a change and that it has been pushed (not released)
+		if (button_difference != 0) {
+
+			// has anything changed based on the buttons?
+			if      (button_difference & 0x04) { print("Stop counting..."); count_direction = STOP; }
+			else if (button_difference & 0x02) { print("Counting down..."); count_direction = DOWN; }
+			else if (button_difference & 0x01) { print("Counting up...");   count_direction = UP;   }
+		}
+		last_button_state = current_button_state;                    // update the button status to prevent runaway button action
+
+		// compute the next sample number (period of 256)
+		if      (count_direction = UP)   { sample++; sample %= ONE_PERIOD; }
+		else if (count_direction = DOWN) { sample--; if (sample < -1) sample = ONE_PERIOD-1; }
+		else                              { /* no change */}
+
+		// do the math and drive the LEDs
+		do_sine_sample(sample);
+
+		// wait loop - caution - delay loops like this are removed when optimization is turned on!
+		delay_loop(LED_delay_max);                                      // delay for a slower display
+
+		// if this is the profiler mode, we need to quit after a while
+#ifdef profiler_test
+		keep_running = profile_iteration_count--;
+#endif
+
+	}
+}
+
+
+// compute sine, drive LEDs and serial port
+// 0 < sample < ONE_PERIOD
+void do_sine_sample(int location_in_period) {
+	// local variables
+	double radian_equivalent;
+	int    sine_value;
+	char   buf[32],*message, *strValue;                         // used in hardware_test mode only
+
+	// do the computation of this point for sine
+	radian_equivalent = (double)(location_in_period)/(double)(ONE_PERIOD) * 3.1415927f * 2.0;   // one full circle
+	sine_value = (int)((double)(AMPLITUDE) * sine(radian_equivalent) / 2);                      // this is +/- (i.e. range -1:1 converted to 0:1), so...
+	sine_value += AMPLITUDE/2;                                                                  // bias this up so that 0 is in the middle
+
+	// drive the bar graph display
+	driveBarGraph(sine_value);
+
+#ifdef hardware_test
+	// display the value on the serial port and wait a bit for the LEDs/user to catch up - but only in hardware test mode
+	// no output will be present in the profiler_test
+	strValue = itoa(sine_value,buf,10);
+	message = strcat(strValue,"...");
+	xil_printf(message);
+#endif
+}
+
+/*
+ * sine(angle in radians)
+ *
+ * where: 0 <= angle in radians <= 2 PI
+ *
+ * does Taylor series expansion (4 terms) to compute sine
+ * taylor series good only for small angles - use reflection technique to determine value outside of Q1
+ * Q2 = PI - x
+ * Q3 = - (x - PI)
+ * Q4 = - (2PI - x)
+ *
+ * Note: this algorithm deliberately uses a slow, iterative way to compute factorials. The faster way:
+ * int factorial[] = { 1, 1, 2, 6, 24, 120, 720, 5040 };           // the "fast" way to do it - precompute for the # of terms you need, then it's just a memory lookup
+ * result = angle_in_radians - X3/factorial[3] + X5/factorial[5] - X7/factorial[7];
+ *
+ */
+double sine(double angle_in_radians) {
+	double X2;
+	double X3;
+	double X5;
+	double X7;
+	double result;
+	int    quadrant   = 1;                            // begin by assuming Q1
+
+	// determine quadrant and reflect horizontally (if necessary)
+	if (angle_in_radians > 3*PI/2) {                  // in Q4?
+		quadrant = 4;                                  // remember for later
+		angle_in_radians = 2 * PI - angle_in_radians;  // do horizontal (x) reflection, y reflection done later
+	} else if (angle_in_radians > PI) {               // in Q3?
+		quadrant = 3;                                  // remember for later
+		angle_in_radians = angle_in_radians - PI;      // no x reflection, y reflection done later
+	} else if (angle_in_radians > PI/2) {             // in Q2?
+		quadrant = 2;                                  // remember for later
+		angle_in_radians = PI - angle_in_radians;      // do horizontal (x) reflection
+	}
+
+	// compute powers of angle_in_radians
+	X2 = angle_in_radians * angle_in_radians;
+	X3 = X2 * angle_in_radians;
+	X5 = X3 * X2;
+	X7 = X5 * X2;
+
+	// compute the sine approximation to 4 places for Q1
+	result = angle_in_radians - X3/factorial(3) + X5/factorial(5) - X7/factorial(7);
+
+	// do vertical reflection for Q3 and Q4
+	if (quadrant > 2) {
+		result *= -1;                                 // flip the Q1/Q2 result
+	}
+
+	return result;
+}
+
+double factorial(int final_term) {
+	double result = 1.0;
+	int    term;
+
+	for (term=2; term<=final_term; term++) {
+		result *= term;
+	}
+
+	return result;
+}
+
+
+/******************************************************************************************************
+ * LINUX GPIO INITIALIZATION
+ * This function performs two operations:
+ * 1) Opens a device to memory window in Linux so a GPIO that exists at a physical address is mapped
+ *    to a fixed logical address. This logical address is returned by the function.
+ * 2) Initialize the GPIO for either input or output mode.
+ *
+ * INPUT PARAMETERS:
+ * gpio_base_address - physical hardware base address of GPIO, you have to get this from XML file
+ * direction - 32 bits indicating direction for each bit; 0 - output; 1 - input
+ * first_call - boolean indicating that this is first call to function. The first time and only the first
+ *              time should the Linux device memory mapping service be mounted. Call for subsequent
+ *              gpio mapping this should be set to FALSE (0).
+ *
+ * RETURNS:
+ * mapped_dev_base - memory pointer to the GPIO that was specified by the gpio_base_address
+ *******************************************************************************************************/
+void *Linux_GPIO_initialize(int gpio_base_address, int direction, int first_call)
+{
+	void *mapped_dev_base;
+	off_t dev_base = gpio_base_address;
+
+	// Linux service to directly access PL hardware as memory without using a device driver
+	// The memory mapping to device service should only be called once
+	if (first_call) {
+		memfd = open("/dev/mem", O_RDWR | O_SYNC);
+		if (memfd == -1) {
+			printf("Can't open /dev/mem.\n");
+			exit(0);
+		}
+		printf("/dev/mem opened.\n");
+	}
+
+	// Map one page of memory into user space such that the device is in that page, but it may not
+	// be at the start of the page.
+	mapped_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, dev_base & ~MAP_MASK);
+	if (mapped_base == (void *) -1) {
+		printf("Can't map the memory to user space for LED GPIO.\n");
+		exit(0);
+	}
+	printf("LED GPIO memory mapped at address %p.\n", mapped_base);
+
+	// Get the address of the device in user space which will be an offset from the base
+	// that was mapped as memory is mapped at the start of a page
+	mapped_dev_base = mapped_base + (dev_base & MAP_MASK);
+
+	// Slight delay for Linux memory access problem
+	usleep(50);
+	// write to the direction GPIO direction register to set as all inputs or outputs
+	*((volatile unsigned long *) (mapped_dev_base + GPIO_DIRECTION_OFFSET)) = direction;
+	return mapped_dev_base;
+}
+
+/*
+ * driveBarGraph(12 bit value)
+ *
+ * calls doBarGraph. this routine determines which of the 8 possible bins/bars should be illuminated
+ *
+ */
+#define NUMBER_OF_LEDS    8
+void driveBarGraph(int value) {
+	char buf[32];                                                    // used in hardware test mode
+	double bin_range = (AMPLITUDE) / (NUMBER_OF_LEDS);               // how large is each bin?
+	int nBars = (int)((double)value / bin_range);                    // how many bars should be lit?
+
+#ifdef hardware_test
+	// only print the diagnostic text in hardware_test mode
+	xil_printf(itoa(nBars,buf,10)); print("\n\r");
+#endif
+
+	// turn on the proper LEDs based on the # of bars and the style
+	doBarGraph(nBars,CYLON);                                        //
+}
+
+
+/*
+ * doBarGraph(device, value to display, style in which to display
+ *
+ *
+ *    example value = 5,    style shown below:    LED  7  6  5  4  3  2  1  0
+ * Style: BAR   - solid up to value                    -  -  *  *  *  *  *  *     * = on, - = off
+ *        CYLON - single bar at value                  -  -  *  -  -  -  -  -
+ *        BINARY- binary representation of value       -  -  -  -  -  *  -  *
+ *        other - displays error pattern               -  *  -  *  -  *  -  *
+ *
+ */
+void doBarGraph(int value, int style) {
+
+	if (style == BAR) {
+		switch (value) {
+			case 0:  LEDs_driver(0x00); break;
+			case 1:  LEDs_driver(0x01); break;
+			case 2:  LEDs_driver(0x03); break;
+			case 3:  LEDs_driver(0x07); break;
+			case 4:  LEDs_driver(0x0f); break;
+			case 5:  LEDs_driver(0x1f); break;
+			case 6:  LEDs_driver(0x3f); break;
+			case 7:  LEDs_driver(0x7f); break;
+			case 8:  LEDs_driver(0xff); break;
+			default: LEDs_driver(0x55);                                          // non-contiguous pattern indicates error
+		}
+	} else if (style == CYLON) {
+		switch (value) {
+			case 0:  LEDs_driver(0x01); break;
+			case 1:  LEDs_driver(0x02); break;
+			case 2:  LEDs_driver(0x04); break;
+			case 3:  LEDs_driver(0x08); break;
+			case 4:  LEDs_driver(0x10); break;
+			case 5:  LEDs_driver(0x20); break;
+			case 6:  LEDs_driver(0x40); break;
+			case 7:  LEDs_driver(0x80); break;
+			default: LEDs_driver(0x55);                                         // non-contiguous pattern indicates error
+		}
+	} else if (style == BINARY) {
+		LEDs_driver(value);                                                    // simple binary value to display
+	} else {
+		LEDs_driver(0x69);                                                     // different error pattern
+	}
+
+}
+
+
+/*
+ * *** buttons_get_state()
+ *
+ * returns an integer representing the value of the buttons
+ *   0 - no buttons pressed
+ *   1 - left/down button pressed
+ *   2 - right/up button pressed
+ *   3 - both buttons pressed
+ *
+ * this function is coded this way so that it is clear what the Linux vs. Standalone/bare-metal are.
+ */
+int buttons_get_state()
+{
+	// local variables
+	int current_button_state = 0;
+	// Linux read of gpio, notice that it accesses the data register of the GPIO as a memory location, no device driver needed!
+	current_button_state = *((volatile unsigned long *) (mapped_button_dev_base + GPIO_DATA_OFFSET));
+}
+
+
+/*
+ * *** LEDs_driver(led image (int))
+ *
+ * sets the LED channel 1 device to the passed value
+ *
+ * this function is coded this way so that it is clear what the Linux vs. Standalone/bare-metal are.
+ */
+void LEDs_driver(int led_image)
+{
+	// Linux write to gpio, by writing to a memory address of the gpio data register, no device driver needed!
+	*((volatile unsigned long *) (mapped_led_dev_base + GPIO_DATA_OFFSET)) = led_image;
+}
+
+
+/*
+ * *** delay_loop(int delay_count)
+ *
+ * finite loop which causes a simple delay
+ * could have been also performed, more accurately, using the usleep() function
+ *
+ */
+void delay_loop(long int count)
+{
+	int i;
+	for (i=0; i<count; i++); 
+}
+
+
+/*
+ * *** itoa
+ *
+ * converts an integer into a string - also found in the C library
+ *
+ */
+char *itoa(int value, char *string, int radix)
+{
+	char tmp[33];
+	char *tp = tmp;
+	int i;
+	unsigned v;
+	int sign;
+	char *sp;
+
+	if (radix > 36 || radix <= 1) { string = "radix out of range 1..36"; return 0; }
+
+	sign = (radix == 10 && value < 0);
+	if (sign) { v = -value; }
+	else      { v = (unsigned)value; }
+	while (v || tp == tmp)  {
+		i = v % radix;
+		v = v / radix;
+		if (i < 10) { *tp++ = i+'0'; }
+		else        { *tp++ = i + 'a' - 10; }
+	}
+
+	if (string == 0) {
+		string = (char *)malloc((tp-tmp)+sign+1);
+		// xil_printf("call to malloc() made\n\r");
+	}
+	sp = string;
+
+	if (sign) { *sp++ = '-'; }
+	while (tp > tmp) { *sp++ = *--tp; }
+	*sp = 0;
+	return string;
+}
+
+/*
+ * *** strcat
+ *
+ * returns the concatonation of two strings
+ *
+ * may also be found in string.h
+ *
+ */
+char * strcat ( char * destination, const char * source ){
+	char *d = destination;
+	while (*d) ++d;
+	while ((*d++ = *source++) != '\0') ;
+	return (destination);
+}
+
+
+
diff --git a/projects/lago_v1_3/adc.tcl b/projects/lago_v1_3/adc.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..ac08dc20c95038028b5f67d9c9627ec14fb304ea
--- /dev/null
+++ b/projects/lago_v1_3/adc.tcl
@@ -0,0 +1,79 @@
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_2 {
+  CONST_WIDTH 16
+  CONST_VAL 1
+}
+
+# Create dc removal circuit
+cell labdpr:user:axis_dc_removal dc_removal_0 {} {
+  aclk /pll_0/clk_out1
+  aresetn /reset_0/Dout
+  S_AXIS /adc_0/M_AXIS
+	k1_i const_2/dout
+	k2_i const_2/dout
+}
+
+# Create pps generator
+cell labdpr:user:pps_gen pps_0 {} {
+  aclk /pll_0/clk_out1
+  aresetn /reset_0/Dout
+}
+
+# Create lago trigger
+cell labdpr:user:axis_lago_trigger trigger_0 {
+  DATA_ARRAY_LENGTH 32
+} {
+  S_AXIS dc_removal_0/M_AXIS
+  aclk /pll_0/clk_out1
+  aresetn /reset_0/Dout
+  trig_lvl_a_i /trig_lvl_a/dout
+  trig_lvl_b_i /trig_lvl_b/dout
+  subtrig_lvl_a_i /subtrig_lvl_a/dout
+  subtrig_lvl_b_i /subtrig_lvl_b/dout
+  pps_i pps_0/pps_o
+  clk_cnt_pps_i pps_0/clk_cnt_pps_o
+  temp_i /reg_temp/dout
+  pressure_i /reg_pressure/dout
+  time_i /reg_time/dout
+  date_i /reg_date/dout
+  latitude_i /reg_latitude/dout
+  longitude_i /reg_longitude/dout
+  altitude_i  /reg_altitude/dout 
+  satellites_i /reg_satellite/dout     
+  scaler_a_i /reg_trig_scaler_a/dout
+  scaler_b_i /reg_trig_scaler_b/dout
+}
+
+# Create the tlast generator
+cell labdpr:user:axis_tlast_gen tlast_gen_0 {
+  AXIS_TDATA_WIDTH 32
+  PKT_CNTR_BITS 32
+} {
+  S_AXIS trigger_0/M_AXIS
+  aclk /pll_0/clk_out1
+  aresetn /reset_1/Dout
+}
+
+# Create axis_dwidth_converter
+cell xilinx.com:ip:axis_dwidth_converter conv_0 {
+  S_TDATA_NUM_BYTES.VALUE_SRC USER
+  S_TDATA_NUM_BYTES 4
+  M_TDATA_NUM_BYTES 8
+} {
+  S_AXIS tlast_gen_0/M_AXIS
+  aclk /pll_0/clk_out1
+  aresetn /reset_2/Dout
+}
+
+# Create axis_ram_writer
+cell labdpr:user:axis_ram_writer writer_0 {
+  ADDR_WIDTH 20
+  AXI_ID_WIDTH 3
+} {
+  aclk /pll_0/clk_out1
+  aresetn /reset_2/Dout
+  S_AXIS conv_0/M_AXIS
+  M_AXI /ps_0/S_AXI_ACP
+}
+
diff --git a/projects/lago_v1_3/block_design.tcl b/projects/lago_v1_3/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..c8dea1e5ce783c1e02b923c46a15bb8b0d07ae4e
--- /dev/null
+++ b/projects/lago_v1_3/block_design.tcl
@@ -0,0 +1,336 @@
+source projects/base_system/block_design.tcl
+
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_0
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0 {} {
+  ext_reset_in const_0/dout
+}
+
+#Enable interrupts
+set_property -dict [list CONFIG.PCW_USE_FABRIC_INTERRUPT {1} CONFIG.PCW_IRQ_F2P_INTR {1}] [get_bd_cells ps_0]
+
+# Delete input/output port
+delete_bd_objs [get_bd_ports exp_p_tri_io]
+delete_bd_objs [get_bd_ports exp_n_tri_io]
+
+# Create input port
+create_bd_port -dir I -from 7 -to 7 exp_n_tri_io
+create_bd_port -dir O -from 7 -to 7 exp_p_tri_io
+create_bd_port -dir I -from 0 -to 0 ext_resetn
+
+# Create axis_rp_adc
+cell labdpr:user:axis_rp_adc adc_0 {
+  ADC_DATA_WIDTH 14
+} {
+  aclk pll_0/clk_out1
+  adc_dat_a adc_dat_a_i
+  adc_dat_b adc_dat_b_i
+  adc_csn adc_csn_o
+}
+
+# Create axi_cfg_register
+cell labdpr:user:axi_cfg_register cfg_0 {
+  CFG_DATA_WIDTH 1024
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+}
+
+#Create concatenator
+cell xilinx.com:ip:xlconcat concat_0 {
+  NUM_PORTS 6
+} {
+  dout led_o
+}
+
+#Create concatenator
+cell xilinx.com:ip:xlconcat concat_1 {
+  NUM_PORTS 4
+} {
+  dout dac_pwm_o
+}
+
+# Create axi_intc
+cell xilinx.com:ip:axi_intc axi_intc_0 {
+  C_IRQ_CONNECTION 1
+  C_S_AXI_ACLK_FREQ_MHZ 125.0
+  C_PROCESSOR_CLK_FREQ_MHZ 125.0
+} {
+  irq ps_0/IRQ_F2P
+}
+
+# Create axi_sts_register
+cell labdpr:user:axi_sts_register sts_0 {
+  STS_DATA_WIDTH 32
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+} { }
+
+# Create xlslice for reset fifo, pps_gen and trigger modules. off=0
+cell labdpr:user:port_slicer reset_0 {
+  DIN_WIDTH 1024 DIN_FROM 0 DIN_TO 0
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for reset tlast_gen. off=0
+cell labdpr:user:port_slicer reset_1 {
+  DIN_WIDTH 1024 DIN_FROM 1 DIN_TO 1
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for reset conv_0 and writer_0. off=0
+cell labdpr:user:port_slicer reset_2 {
+  DIN_WIDTH 1024 DIN_FROM 2 DIN_TO 2
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for set the # of samples to get. off=1
+cell labdpr:user:port_slicer nsamples {
+  DIN_WIDTH 1024 DIN_FROM 63 DIN_TO 32
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for set the trigger_lvl_a. off=2
+cell labdpr:user:port_slicer trig_lvl_a {
+  DIN_WIDTH 1024 DIN_FROM 95 DIN_TO 64
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for set the trigger_lvl_b. off=3
+cell labdpr:user:port_slicer trig_lvl_b {
+  DIN_WIDTH 1024 DIN_FROM 127 DIN_TO 96
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for set the subtrigger_lvl_a. off=4
+cell labdpr:user:port_slicer subtrig_lvl_a {
+  DIN_WIDTH 1024 DIN_FROM 159 DIN_TO 128
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for set the subtrigger_lvl_b. off=5
+cell labdpr:user:port_slicer subtrig_lvl_b {
+  DIN_WIDTH 1024 DIN_FROM 191 DIN_TO 160
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the temperature data. off=6
+cell labdpr:user:port_slicer reg_temp {
+  DIN_WIDTH 1024 DIN_FROM 223 DIN_TO 192
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the pressure data. off=7
+cell labdpr:user:port_slicer reg_pressure {
+  DIN_WIDTH 1024 DIN_FROM 255 DIN_TO 224
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the time data. off=8
+cell labdpr:user:port_slicer reg_time {
+  DIN_WIDTH 1024 DIN_FROM 287 DIN_TO 256
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the date data. off=9
+cell labdpr:user:port_slicer reg_date {
+  DIN_WIDTH 1024 DIN_FROM 319 DIN_TO 288
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the latitude data. off=10
+cell labdpr:user:port_slicer reg_latitude {
+  DIN_WIDTH 1024 DIN_FROM 351 DIN_TO 320
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the longitude data. off=11
+cell labdpr:user:port_slicer reg_longitude {
+  DIN_WIDTH 1024 DIN_FROM 383 DIN_TO 352
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the altitude data. off=12
+cell labdpr:user:port_slicer reg_altitude {
+  DIN_WIDTH 1024 DIN_FROM 415 DIN_TO 384
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the satellite data. off=13
+cell labdpr:user:port_slicer reg_satellite {
+  DIN_WIDTH 1024 DIN_FROM 447 DIN_TO 416
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the trigger scaler a. off=14
+cell labdpr:user:port_slicer reg_trig_scaler_a {
+  DIN_WIDTH 1024 DIN_FROM 479 DIN_TO 448
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the trigger scaler b. off=15
+cell labdpr:user:port_slicer reg_trig_scaler_b {
+  DIN_WIDTH 1024 DIN_FROM 511 DIN_TO 480
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer for cfg RAM writer. off=22
+cell labdpr:user:port_slicer cfg_ram_wr {
+  DIN_WIDTH 1024 DIN_FROM 735 DIN_TO 704
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for set the gpsen_i input
+cell labdpr:user:port_slicer gpsen {
+  DIN_WIDTH 1024 DIN_FROM 4 DIN_TO 4
+} {
+  din cfg_0/cfg_data
+}
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_1 {} {
+  slowest_sync_clk pll_0/clk_out1
+  dcm_locked pll_0/locked
+  ext_reset_in ext_resetn
+}
+
+module fadc_0 {
+  source projects/lago_v1_3/adc.tcl
+} {
+  writer_0/sts_data sts_0/sts_data 
+  pps_0/resetn_i rst_1/peripheral_aresetn 
+  pps_0/int_o axi_intc_0/intr
+	writer_0/cfg_data cfg_ram_wr/dout
+	writer_0/M_AXI ps_0/S_AXI_ACP
+	tlast_gen_0/pkt_length nsamples/dout
+	pps_0/gpsen_i gpsen/dout
+  pps_0/pps_i exp_n_tri_io
+  pps_0/pps_sig_o exp_p_tri_io
+  pps_0/pps_gps_led_o concat_0/In0
+  pps_0/false_pps_led_o concat_0/In1
+}
+
+#Now all related to the DAC PWM
+# Create xlslice. off=0
+cell labdpr:user:port_slicer reset_3 {
+  DIN_WIDTH 1024 DIN_FROM 3 DIN_TO 3
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice. off=16
+cell labdpr:user:port_slicer cfg_dac_pwm_0 {
+  DIN_WIDTH 1024 DIN_FROM 543 DIN_TO 512
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice.. off=17
+cell labdpr:user:port_slicer cfg_dac_pwm_1 {
+  DIN_WIDTH 1024 DIN_FROM 575 DIN_TO 544
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice.. off=18
+cell labdpr:user:port_slicer cfg_dac_pwm_2 {
+  DIN_WIDTH 1024 DIN_FROM 607 DIN_TO 576
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice.. off=19
+cell labdpr:user:port_slicer cfg_dac_pwm_3 {
+  DIN_WIDTH 1024 DIN_FROM 639 DIN_TO 608
+} {
+  din cfg_0/cfg_data
+}
+
+module slow_dac_0 {
+  source projects/lago_v1_3/slow_dac.tcl
+} {
+	gen_0/pwm_o	concat_1/In0
+	gen_0/led_o concat_0/In2
+	gen_0/data_i cfg_dac_pwm_0/Dout
+	gen_1/pwm_o	concat_1/In1
+	gen_1/led_o concat_0/In3
+	gen_1/data_i cfg_dac_pwm_1/Dout
+	gen_2/pwm_o	concat_1/In2
+	gen_2/led_o concat_0/In4
+	gen_2/data_i cfg_dac_pwm_2/Dout
+	gen_3/pwm_o	concat_1/In3
+	gen_3/led_o concat_0/In5
+	gen_3/data_i cfg_dac_pwm_3/Dout
+}
+
+#XADC related
+# Create xadc
+cell xilinx.com:ip:xadc_wiz xadc_wiz_0 {
+	DCLK_FREQUENCY 125
+	ADC_CONVERSION_RATE 500
+  XADC_STARUP_SELECTION channel_sequencer
+	CHANNEL_AVERAGING 64
+  OT_ALARM false
+  USER_TEMP_ALARM false
+  VCCINT_ALARM false
+  VCCAUX_ALARM false
+  ENABLE_VCCPINT_ALARM false
+  ENABLE_VCCPAUX_ALARM false
+  ENABLE_VCCDDRO_ALARM false
+  CHANNEL_ENABLE_CALIBRATION true
+  CHANNEL_ENABLE_TEMPERATURE true
+  CHANNEL_ENABLE_VCCINT true
+  CHANNEL_ENABLE_VP_VN true
+  CHANNEL_ENABLE_VAUXP0_VAUXN0 true
+  CHANNEL_ENABLE_VAUXP1_VAUXN1 true
+  CHANNEL_ENABLE_VAUXP8_VAUXN8 true
+  CHANNEL_ENABLE_VAUXP9_VAUXN9 true
+  AVERAGE_ENABLE_VP_VN true
+  AVERAGE_ENABLE_VAUXP0_VAUXN0 true
+  AVERAGE_ENABLE_VAUXP1_VAUXN1 true
+  AVERAGE_ENABLE_VAUXP8_VAUXN8 true
+  AVERAGE_ENABLE_VAUXP9_VAUXN9 true
+  AVERAGE_ENABLE_TEMPERATURE true
+  AVERAGE_ENABLE_VCCINT true
+  EXTERNAL_MUX_CHANNEL VP_VN
+  SINGLE_CHANNEL_SELECTION TEMPERATURE
+} {}
+
+connect_bd_intf_net [get_bd_intf_ports Vp_Vn] [get_bd_intf_pins xadc_wiz_0/Vp_Vn]
+connect_bd_intf_net [get_bd_intf_ports Vaux0] [get_bd_intf_pins xadc_wiz_0/Vaux0]
+connect_bd_intf_net [get_bd_intf_ports Vaux1] [get_bd_intf_pins xadc_wiz_0/Vaux1]
+connect_bd_intf_net [get_bd_intf_ports Vaux8] [get_bd_intf_pins xadc_wiz_0/Vaux8]
+connect_bd_intf_net [get_bd_intf_ports Vaux9] [get_bd_intf_pins xadc_wiz_0/Vaux9]
+
+addr 0x40000000 4K axi_intc_0/S_AXI /ps_0/M_AXI_GP0
+
+addr 0x40001000 4K cfg_0/S_AXI /ps_0/M_AXI_GP0
+
+addr 0x40002000 4K sts_0/S_AXI /ps_0/M_AXI_GP0
+
+addr 0x40003000 4K xadc_wiz_0/s_axi_lite /ps_0/M_AXI_GP0
+
+
+group_bd_cells PS7 [get_bd_cells rst_0] [get_bd_cells rst_1] [get_bd_cells pll_0] [get_bd_cells const_0] [get_bd_cells ps_0] [get_bd_cells ps_0_axi_periph]
+
diff --git a/projects/lago_v1_3/ports.xdc b/projects/lago_v1_3/ports.xdc
new file mode 100644
index 0000000000000000000000000000000000000000..ff256d11c022b18c3865e2caec0b33af40abd6f5
--- /dev/null
+++ b/projects/lago_v1_3/ports.xdc
@@ -0,0 +1,7 @@
+set_property IOSTANDARD LVCMOS33 [get_ports {ext_resetn}]
+set_property SLEW FAST [get_ports {ext_resetn}]
+set_property DRIVE 8 [get_ports {ext_resetn}]
+set_property PULLTYPE PULLUP [get_ports {ext_resetn}]
+
+set_property PACKAGE_PIN J16 [get_ports {ext_resetn}]
+
diff --git a/projects/lago_v1_3/slow_dac.tcl b/projects/lago_v1_3/slow_dac.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..03ac194549e07eac3671f99b10e12af12460f9a6
--- /dev/null
+++ b/projects/lago_v1_3/slow_dac.tcl
@@ -0,0 +1,40 @@
+#Create PWM generator
+cell labdpr:user:ramp_gen:1.0 gen_0 {
+  COUNT_NBITS 20
+  COUNT_MOD 5000
+  DATA_BITS 16
+} {
+	aclk /pll_0/clk_out1
+  aresetn /reset_3/Dout
+}
+
+#Create PWM generator
+cell labdpr:user:ramp_gen:1.0 gen_1 {
+  COUNT_NBITS 20
+  COUNT_MOD 5000
+  DATA_BITS 16
+} {
+	aclk /pll_0/clk_out1
+  aresetn /reset_3/Dout
+}
+
+#Create PWM generator
+cell labdpr:user:ramp_gen:1.0 gen_2 {
+  COUNT_NBITS 20
+  COUNT_MOD 5000
+  DATA_BITS 16
+} {
+	aclk /pll_0/clk_out1
+  aresetn /reset_3/Dout
+}
+
+#Create PWM generator
+cell labdpr:user:ramp_gen:1.0 gen_3 {
+  COUNT_NBITS 20
+  COUNT_MOD 5000
+  DATA_BITS 16
+} {
+	aclk /pll_0/clk_out1
+  aresetn /reset_3/Dout
+}
+
diff --git a/projects/lago_v1_3/src/Makefile b/projects/lago_v1_3/src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d9b4e5552811e84ccd2b0acc75a8fa438eed4161
--- /dev/null
+++ b/projects/lago_v1_3/src/Makefile
@@ -0,0 +1,16 @@
+CC=gcc
+FLAGS=-Wall -O3 -li2c
+ARCH=arm
+CROSS_COMPILE=arm-xilinx-linux-gnueabi-
+
+####
+PROG=lago
+EXTRA=uart_rp.c nmea_rp.c gps_rp.c zynq_io.c bmp180.c
+
+all: $(PROG)
+
+$(PROG): $(PROG).c $(EXTRA) 
+	$(CC) $(FLAGS) -o $(PROG) $(PROG).c $(EXTRA) -lm -lpthread
+
+clean:
+	rm -f $(PROG)
diff --git a/projects/lago_v1_3/src/bmp180.c b/projects/lago_v1_3/src/bmp180.c
new file mode 100644
index 0000000000000000000000000000000000000000..99f3323e9d5df8a586793ad052bd81755b181b42
--- /dev/null
+++ b/projects/lago_v1_3/src/bmp180.c
@@ -0,0 +1,366 @@
+#include "bmp180.h"
+
+/* Lookup table for BMP180 register addresses */
+int32_t bmp180_register_table[11][2] = 
+{
+    {BMP180_REG_AC1_H, 1},
+    {BMP180_REG_AC2_H, 1},
+    {BMP180_REG_AC3_H, 1},
+    {BMP180_REG_AC4_H, 0},
+    {BMP180_REG_AC5_H, 0},
+    {BMP180_REG_AC6_H, 0},
+    {BMP180_REG_B1_H, 1},
+    {BMP180_REG_B2_H, 1},
+    {BMP180_REG_MB_H, 1},
+    {BMP180_REG_MC_H, 1},
+    {BMP180_REG_MD_H, 1}
+};
+
+/*
+ * Returns the raw measured temperature value of this BMP180 sensor.
+ * 
+ * @param bmp180 sensor
+ */
+static int32_t bmp180_read_raw_temperature(void *_bmp) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	i2c_smbus_write_byte_data(bmp->file, BMP180_CTRL, BMP180_TMP_READ_CMD);
+
+	usleep(BMP180_TMP_READ_WAIT_US);
+	int32_t data = i2c_smbus_read_word_data(bmp->file, BMP180_REG_TMP) & 0xFFFF;
+	
+	data = ((data << 8) & 0xFF00) + (data >> 8);
+	
+	return data;
+}
+
+/*
+ * Returns the raw measured pressure value of this BMP180 sensor.
+ * 
+ * @param bmp180 sensor
+ */
+static int32_t bmp180_read_raw_pressure(void *_bmp, uint8_t oss) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	uint16_t wait;
+	uint8_t cmd;
+	
+	switch(oss) {
+		case BMP180_PRE_OSS1:
+			wait = BMP180_PRE_OSS1_WAIT_US; cmd = BMP180_PRE_OSS1_CMD;
+			break;
+		
+		case BMP180_PRE_OSS2:
+			wait = BMP180_PRE_OSS2_WAIT_US; cmd = BMP180_PRE_OSS2_CMD;
+			break;
+		
+		case BMP180_PRE_OSS3:
+			wait = BMP180_PRE_OSS3_WAIT_US; cmd = BMP180_PRE_OSS3_CMD;
+			break;
+		
+		case BMP180_PRE_OSS0:
+		default:
+			wait = BMP180_PRE_OSS0_WAIT_US; cmd = BMP180_PRE_OSS0_CMD;
+			break;
+	}
+	
+	i2c_smbus_write_byte_data(bmp->file, BMP180_CTRL, cmd);
+
+	usleep(wait);
+	
+	int32_t msb, lsb, xlsb, data;
+	msb = i2c_smbus_read_byte_data(bmp->file, BMP180_REG_PRE) & 0xFF;
+	lsb = i2c_smbus_read_byte_data(bmp->file, BMP180_REG_PRE+1) & 0xFF;
+	xlsb = i2c_smbus_read_byte_data(bmp->file, BMP180_REG_PRE+2) & 0xFF;
+	
+	data = ((msb << 16)  + (lsb << 8)  + xlsb) >> (8 - bmp->oss);
+	
+	return data;
+}
+
+/**
+ * Returns the measured pressure in pascal.
+ * 
+ * @param bmp180 sensor
+ * @return pressure
+ */
+float bmp180_pressure(void *_bmp) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	long UT, UP, B6, B5, X1, X2, X3, B3, p;
+	unsigned long B4, B7;
+	
+	UT = bmp180_read_raw_temperature(_bmp);
+	UP = bmp180_read_raw_pressure(_bmp, bmp->oss);
+	
+	X1 = ((UT - bmp->ac6) * bmp->ac5) >> 15;
+	X2 = (bmp->mc << 11) / (X1 + bmp->md);
+	
+	B5 = X1 + X2;
+	
+	B6 = B5 - 4000;
+	
+	X1 = (bmp->b2 * (B6 * B6) >> 12) >> 11;
+	X2 = (bmp->ac2 * B6) >> 11;
+	X3 = X1 + X2;
+	
+	B3 = ((((bmp->ac1 * 4) + X3) << bmp->oss) + 2) / 4;
+	X1 = (bmp->ac3 * B6) >> 13;
+	X2 = (bmp->b1 * ((B6 * B6) >> 12)) >> 16;
+	X3 = ((X1 + X2) + 2) >> 2;
+	
+	
+	B4 = bmp->ac4 * (unsigned long)(X3 + 32768) >> 15;
+	B7 = ((unsigned long) UP - B3) * (50000 >> bmp->oss);
+	
+	if(B7 < 0x80000000) {
+		p = (B7 * 2) / B4;
+	} else {
+		p = (B7 / B4) * 2;
+	}
+	
+	X1 = (p >> 8) * (p >> 8);
+	X1 = (X1 * 3038) >> 16;
+	X2 = (-7357 * p) >> 16;
+	p = p + ((X1 + X2 + 3791) >> 4);
+	
+	return p;
+}
+
+/*
+ * Sets the address for the i2c device file.
+ * 
+ * @param bmp180 sensor
+ */
+static int bmp180_set_addr(void *_bmp) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	int error;
+
+	if((error = ioctl(bmp->file, I2C_SLAVE, bmp->address)) < 0) {
+		DEBUG("error: ioctl() failed\n");
+	}
+
+	return error;
+}
+
+/*
+ * Frees allocated memory in the init function.
+ * 
+ * @param bmp180 sensor
+ */
+static void bmp180_init_error_cleanup(void *_bmp) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	
+	if(bmp->i2c_device != NULL) {
+		free(bmp->i2c_device);
+		bmp->i2c_device = NULL;
+	}
+	
+	free(bmp);
+	bmp = NULL;
+}
+
+/*
+ * Reads a single calibration coefficient from the BMP180 eprom.
+ * 
+ * @param bmp180 sensor
+ */
+static void bmp180_read_eprom_reg(void *_bmp, int32_t *_store, uint8_t reg, int32_t sign) 
+{
+	bmp180_t *bmp = TO_BMP(_bmp);
+	int32_t data = i2c_smbus_read_word_data(bmp->file, reg) & 0xFFFF;
+	
+	// i2c_smbus_read_word_data assumes little endian 
+	// but ARM uses big endian. Thus the ordering of the bytes is reversed.
+	// data = 	 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15   bit position
+	//          |      lsb      |          msb        |  
+	
+	//                 msb           +     lsb
+	*_store = ((data << 8) & 0xFF00) + (data >> 8);
+	
+	if(sign && (*_store > 32767)) {
+		*_store -= 65536;
+	}
+}
+
+/*
+ * Reads the eprom of this BMP180 sensor.
+ * 
+ * @param bmp180 sensor
+ */
+void bmp180_read_eprom(void *_bmp) 
+{
+	bmp180_t *bmp = TO_BMP(_bmp);	
+	
+	int32_t *bmp180_register_addr[11] = {
+		&bmp->ac1, &bmp->ac2, &bmp->ac3, &bmp->ac4, &bmp->ac5, &bmp->ac6,
+		&bmp->b1, &bmp->b2, &bmp->mb, &bmp->mc, &bmp->md
+	};
+	
+	uint8_t sign, reg;
+	int32_t *data;
+	int i;
+	for(i = 0; i < 11; i++) {
+		reg = (uint8_t) bmp180_register_table[i][0];
+		sign = (uint8_t) bmp180_register_table[i][1];
+		data = bmp180_register_addr[i];
+		bmp180_read_eprom_reg(_bmp, data, reg, sign);
+	}
+}
+
+/**
+ * Dumps the eprom values of this BMP180 sensor.
+ * 
+ * @param bmp180 sensor
+ * @param bmp180 eprom struct
+ */
+void bmp180_dump_eprom(void *_bmp, bmp180_eprom_t *eprom) 
+{
+	bmp180_t *bmp = TO_BMP(_bmp);
+	eprom->ac1 = bmp->ac1;
+	eprom->ac2 = bmp->ac2;
+	eprom->ac3 = bmp->ac3;
+	eprom->ac4 = bmp->ac4;
+	eprom->ac5 = bmp->ac5;
+	eprom->ac6 = bmp->ac6;
+	eprom->b1 = bmp->b1;
+	eprom->b2 = bmp->b2;
+	eprom->mb = bmp->mb;
+	eprom->mc = bmp->mc;
+	eprom->md = bmp->md;
+}
+
+/**
+ * Creates a BMP180 sensor object.
+ *
+ * @param i2c device address
+ * @param i2c device file path
+ * @return bmp180 sensor
+ */
+void *bmp180_init(int address, const char* i2c_device_filepath) 
+{
+	DEBUG("device: init using address %#x and i2cbus %s\n", address, i2c_device_filepath);
+	
+	// setup BMP180
+	void *_bmp = malloc(sizeof(bmp180_t));
+	if(_bmp == NULL)  {
+		DEBUG("error: malloc returns NULL pointer\n");
+		return NULL;
+	}
+
+	bmp180_t *bmp = TO_BMP(_bmp);
+	bmp->address = address;
+
+	// setup i2c device path
+	bmp->i2c_device = (char*) malloc(strlen(i2c_device_filepath) * sizeof(char));
+	if(bmp->i2c_device == NULL) {
+		DEBUG("error: malloc returns NULL pointer!\n");
+		bmp180_init_error_cleanup(bmp);
+		return NULL;
+	}
+
+	// copy string
+	strcpy(bmp->i2c_device, i2c_device_filepath);
+	
+	// open i2c device
+	int file;
+	if((file = open(bmp->i2c_device, O_RDWR)) < 0) {
+		DEBUG("error: %s open() failed\n", bmp->i2c_device);
+		bmp180_init_error_cleanup(bmp);
+		return NULL;
+	}
+	bmp->file = file;
+
+	// set i2c device address
+	if(bmp180_set_addr(_bmp) < 0) {
+		bmp180_init_error_cleanup(bmp);
+		return NULL;
+	}
+
+	// setup i2c device
+	bmp180_read_eprom(_bmp);
+	bmp->oss = 0;
+	
+	DEBUG("device: open ok\n");
+
+	return _bmp;
+}
+
+/**
+ * Closes a BMP180 object.
+ * 
+ * @param bmp180 sensor
+ */
+void bmp180_close(void *_bmp) 
+{
+	if(_bmp == NULL) {
+		return;
+	}
+	
+	DEBUG("close bmp180 device\n");
+	bmp180_t *bmp = TO_BMP(_bmp);
+	
+	if(close(bmp->file) < 0) {
+		DEBUG("error: %s close() failed\n", bmp->i2c_device);
+	}
+	
+	free(bmp->i2c_device); // free string
+	bmp->i2c_device = NULL;
+	free(bmp); // free bmp structure
+	_bmp = NULL;
+} 
+
+/**
+ * Returns the measured temperature in celsius.
+ * 
+ * @param bmp180 sensor
+ * @return temperature
+ */
+float bmp180_temperature(void *_bmp) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	long UT, X1, X2, B5;
+	float T;
+	
+	UT = bmp180_read_raw_temperature(_bmp);
+	
+	DEBUG("UT=%lu\n",UT);
+	
+	X1 = ((UT - bmp->ac6) * bmp->ac5) >> 15;
+	X2 = (bmp->mc << 11) / (X1 + bmp->md);
+	B5 = X1 + X2;
+	T = ((B5 + 8) >> 4) / 10.0;
+	
+	return T;
+}
+
+/**
+ * Returns altitude in meters based on the measured pressure 
+ * and temperature of this sensor.
+ * 
+ * @param bmp180 sensor
+ * @return altitude
+ */
+float bmp180_altitude(void *_bmp) 
+{
+	float p, alt;
+	p = bmp180_pressure(_bmp);
+	alt = 44330 * (1 - pow(( (p/100) / BMP180_SEA_LEVEL),1/5.255));
+	
+	return alt;
+}
+
+/**
+ * Sets the oversampling setting for this sensor.
+ * 
+ * @param bmp180 sensor
+ * @param oversampling mode
+ */
+void bmp180_set_oss(void *_bmp, int oss) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	bmp->oss = oss;
+}
+
diff --git a/projects/lago_v1_3/src/bmp180.h b/projects/lago_v1_3/src/bmp180.h
new file mode 100644
index 0000000000000000000000000000000000000000..ecaaab8dfbd37825238eb31c05e57073fff3d1c4
--- /dev/null
+++ b/projects/lago_v1_3/src/bmp180.h
@@ -0,0 +1,142 @@
+#ifndef __BMP180__
+#define __BMP180__
+
+#include <string.h> 
+#include <stdlib.h> 
+#include <fcntl.h> 
+#include <sys/ioctl.h>
+#include <i2c/smbus.h> 
+#include <linux/i2c-dev.h> 
+#include <math.h> 
+#include<unistd.h>
+#include<inttypes.h>
+
+#define BMP180_PRE_OSS0 0 // ultra low power
+#define BMP180_PRE_OSS1 1 // standard
+#define BMP180_PRE_OSS2 2 // high resolution
+#define BMP180_PRE_OSS3 3 // ultra high resoultion
+
+/* AC register */
+#define BMP180_REG_AC1_H 0xAA
+#define BMP180_REG_AC2_H 0xAC
+#define BMP180_REG_AC3_H 0xAE
+#define BMP180_REG_AC4_H 0xB0
+#define BMP180_REG_AC5_H 0xB2
+#define BMP180_REG_AC6_H 0xB4
+
+/* B1 register */
+#define BMP180_REG_B1_H 0xB6
+
+/* B2 register */
+#define BMP180_REG_B2_H 0xB8
+
+/* MB register */
+#define BMP180_REG_MB_H 0xBA
+
+/* MC register */
+#define BMP180_REG_MC_H 0xBC
+
+/* MD register */
+#define BMP180_REG_MD_H 0xBE
+
+/* AC register */
+#define BMP180_CTRL 0xF4
+
+/* Temperature register */
+#define BMP180_REG_TMP 0xF6
+
+/* Pressure register */
+#define BMP180_REG_PRE 0xF6
+
+/* Temperature read command */
+#define BMP180_TMP_READ_CMD 0x2E
+
+/* Waiting time in us for reading temperature values */
+#define BMP180_TMP_READ_WAIT_US 5000
+
+/* Pressure oversampling modes */
+#define BMP180_PRE_OSS0 0 // ultra low power
+#define BMP180_PRE_OSS1 1 // standard
+#define BMP180_PRE_OSS2 2 // high resolution
+#define BMP180_PRE_OSS3 3 // ultra high resoultion
+
+/* Pressure read commands */
+#define BMP180_PRE_OSS0_CMD 0x34
+#define BMP180_PRE_OSS1_CMD 0x74
+#define BMP180_PRE_OSS2_CMD 0xB4
+#define BMP180_PRE_OSS3_CMD 0xF4
+
+/* Waiting times in us for reading pressure values */
+#define BMP180_PRE_OSS0_WAIT_US 5000
+#define BMP180_PRE_OSS1_WAIT_US 8000
+#define BMP180_PRE_OSS2_WAIT_US 14000
+#define BMP180_PRE_OSS3_WAIT_US 26000
+
+/* Average sea-level pressure in hPa */
+#define BMP180_SEA_LEVEL 1013.25
+
+/* Define debug function. */
+//#define __BMP180_DEBUG__
+#ifdef __BMP180_DEBUG__
+#define DEBUG(...)  printf(__VA_ARGS__)
+#else
+#define DEBUG(...)
+#endif
+
+/* Shortcut to cast void pointer to a bmp180_t pointer */
+#define TO_BMP(x) (bmp180_t*) x
+
+/* Basic structure for the bmp180 sensor */
+typedef struct {
+				/* file descriptor */
+				int file;
+				/* i2c device address */
+				int address;
+				/* BMP180 oversampling mode */
+				int oss;
+				/* i2c device file path */
+				char *i2c_device;
+				/* Eprom values */
+				int32_t ac1;
+				int32_t ac2;
+				int32_t ac3;
+				int32_t ac4;
+				int32_t ac5;
+				int32_t ac6;
+				int32_t b1;
+				int32_t b2;
+				int32_t mb;
+				int32_t mc;
+				int32_t md;
+} bmp180_t;
+
+
+/* Lookup table for BMP180 register addresses */
+extern int32_t bmp180_register_table[11][2];
+
+typedef struct {
+				/* Eprom values */
+				int ac1;
+				int ac2;
+				int ac3;
+				int ac4;
+				int ac5;
+				int ac6;
+				int b1;
+				int b2;
+				int mb;
+				int mc;
+				int md;
+} bmp180_eprom_t;
+
+/* Prototypes for helper functions */
+void bmp180_read_eprom(void *_bmp);
+void *bmp180_init(int address, const char* i2c_device_filepath);
+void bmp180_close(void *_bmp);
+void bmp180_set_oss(void *_bmp, int oss);
+float bmp180_pressure(void *_bmp);
+float bmp180_temperature(void *_bmp);
+float bmp180_altitude(void *_bmp);
+void bmp180_dump_eprom(void *_bmp, bmp180_eprom_t *eprom);
+
+#endif
diff --git a/projects/lago_v1_3/src/defs.h b/projects/lago_v1_3/src/defs.h
new file mode 100644
index 0000000000000000000000000000000000000000..104ff7078f07d06663424fda158256f8b6c4d444
--- /dev/null
+++ b/projects/lago_v1_3/src/defs.h
@@ -0,0 +1,136 @@
+#define  _CRT_SECURE_NO_WARNINGS
+
+#define _FILE_OFFSET_BITS  64
+
+#ifndef EXP
+#define EXP "LAGO"
+#endif
+
+/* Output format version */
+#define DATAVERSION 			5
+#define VERSION 				2
+#define REVISION	 			1
+
+#define MAXCHRLEN 				1024
+#define BLOCKSIZE				16384
+#define MAXFILENAMELEN			255
+#define MAXPRESS 				1100 //1100Hpa
+#define PRESSUREBLOCKSIZE		22
+#define GPSBLOCKSIZE 			64
+
+#define XIL_AXI_INTC_BASEADDR 0x40000000
+#define XIL_AXI_INTC_HIGHADDR 0x40000FFF
+
+#define XIL_AXI_INTC_ISR_OFFSET    0x0
+#define XIL_AXI_INTC_IPR_OFFSET    0x4
+#define XIL_AXI_INTC_IER_OFFSET    0x8
+#define XIL_AXI_INTC_IAR_OFFSET    0xC
+#define XIL_AXI_INTC_SIE_OFFSET    0x10
+#define XIL_AXI_INTC_CIE_OFFSET    0x14
+#define XIL_AXI_INTC_IVR_OFFSET    0x18
+#define XIL_AXI_INTC_MER_OFFSET    0x1C
+#define XIL_AXI_INTC_IMR_OFFSET    0x20
+#define XIL_AXI_INTC_ILR_OFFSET    0x24
+#define XIL_AXI_INTC_IVAR_OFFSET   0x100
+
+#define XIL_AXI_INTC_MER_ME_MASK 0x00000001
+#define XIL_AXI_INTC_MER_HIE_MASK 0x00000002
+
+//CFG
+#define CFG_RESET_GRAL_OFFSET    0x0
+#define CFG_NSAMPLES_OFFSET      0x4
+#define CFG_TRLVL_1_OFFSET       0x8
+#define CFG_TRLVL_2_OFFSET       0xC
+#define CFG_STRLVL_1_OFFSET      0x10
+#define CFG_STRLVL_2_OFFSET      0x14
+#define CFG_TEMPERATURE_OFFSET   0x18
+#define CFG_PRESSURE_OFFSET      0x1C
+#define CFG_TIME_OFFSET          0x20
+#define CFG_LATITUDE_OFFSET      0x24
+#define CFG_LONGITUDE_OFFSET     0x28
+#define CFG_ALTITUDE_OFFSET      0x2C
+#define CFG_SATELLITE_OFFSET     0x30
+#define CFG_HV1_OFFSET           0x40
+#define CFG_HV2_OFFSET           0x44
+
+//CFG Slow DAC
+#define CFG_DAC_PWM0_OFFSET 0x40
+#define CFG_DAC_PWM1_OFFSET 0x44
+#define CFG_DAC_PWM2_OFFSET 0x48
+#define CFG_DAC_PWM3_OFFSET 0x4C
+
+#define ENBL_ALL_MASK         0xFFFFFFFF
+#define RST_ALL_MASK          0x00000000
+#define RST_PPS_TRG_FIFO_MASK 0x00000001
+#define RST_TLAST_GEN_MASK    0x00000002
+#define RST_WRITER_MASK       0x00000004
+#define RST_AO_MASK           0x00000008
+#define FGPS_EN_MASK          0x00000010
+
+//STS
+#define STS_STATUS_OFFSET     0x0
+
+//XADC
+#define XADC_SRR_OFFSET          0x0
+#define XADC_SR_OFFSET           0x4
+#define XADC_AOSR_OFFSET         0x8
+#define XADC_CONVSTR_OFFSET      0xC
+#define XADC_SYSMONRR_OFFSET     0x10
+#define XADC_GIER_OFFSET         0x5C
+#define XADC_IPISR_OFFSET        0x60
+#define XADC_IPIER_OFFSET        0x68
+#define XADC_TEMPERATURE_OFFSET  0x200
+#define XADC_VCCINT_OFFSET       0x204
+#define XADC_VCCAUX_OFFSET       0x208
+#define XADC_VPVN_OFFSET         0x20C
+#define XADC_VREFP_OFFSET        0x210
+#define XADC_VREFN_OFFSET        0x214
+#define XADC_VBRAM_OFFSET        0x218
+#define XADC_UNDEF_OFFSET        0x21C
+#define XADC_SPLYOFF_OFFSET      0x220
+#define XADC_ADCOFF_OFFSET       0x224
+#define XADC_GAIN_ERR_OFFSET     0x228
+#define XADC_ZDC_SPLY_OFFSET     0x234
+#define XADC_ZDC_AUX_SPLY_OFFSET 0x238
+#define XADC_ZDC_MEM_SPLY_OFFSET 0x23C
+#define XADC_VAUX_PN_0_OFFSET    0x240
+#define XADC_VAUX_PN_1_OFFSET    0x244
+#define XADC_VAUX_PN_2_OFFSET    0x248
+#define XADC_VAUX_PN_3_OFFSET    0x24C
+#define XADC_VAUX_PN_4_OFFSET    0x250
+#define XADC_VAUX_PN_5_OFFSET    0x254
+#define XADC_VAUX_PN_6_OFFSET    0x258
+#define XADC_VAUX_PN_7_OFFSET    0x25C
+#define XADC_VAUX_PN_8_OFFSET    0x260
+#define XADC_VAUX_PN_9_OFFSET    0x264
+#define XADC_VAUX_PN_10_OFFSET   0x268
+#define XADC_VAUX_PN_11_OFFSET   0x26C
+#define XADC_VAUX_PN_12_OFFSET   0x270
+#define XADC_VAUX_PN_13_OFFSET   0x274
+#define XADC_VAUX_PN_14_OFFSET   0x278
+#define XADC_VAUX_PN_15_OFFSET   0x27C
+
+#define XADC_AI0_OFFSET XADC_VAUX_PN_8_OFFSET
+#define XADC_AI1_OFFSET XADC_VAUX_PN_0_OFFSET
+#define XADC_AI2_OFFSET XADC_VAUX_PN_1_OFFSET
+#define XADC_AI3_OFFSET XADC_VAUX_PN_9_OFFSET
+
+#define XADC_CONV_VAL 0.00171191993362 //(A_ip/2^12)*(34.99/4.99)
+
+
+//#define XIL_AXI_INTC_IPISR_INT_OCCURED_MASK 0x00000001
+//#define XIL_AXI_INTC2_IPISR_INT_OCCURED_MASK  0x00000002
+//#define XIL_AXI_INTC_GIER_ENABLE_INT_MASK 0x80000000
+//
+//#define XIL_AXI_INTC_CSR_CASC_MASK    0x00000800
+//#define XIL_AXI_INTC_CSR_ENABLE_ALL_MASK  0x00000400
+//#define XIL_AXI_INTC_CSR_ENABLE_PWM_MASK  0x00000200
+//#define XIL_AXI_INTC_CSR_ENABLE_TMR_MASK  0x00000080
+//#define XIL_AXI_INTC_CSR_ENABLE_INT_MASK  0x00000040
+//#define XIL_AXI_INTC_CSR_LOAD_MASK    0x00000020
+//#define XIL_AXI_INTC_CSR_AUTO_RELOAD_MASK 0x00000010
+//#define XIL_AXI_INTC_CSR_EXT_CAPTURE_MASK 0x00000008
+//#define XIL_AXI_INTC_CSR_EXT_GENERATE_MASK  0x00000004
+//#define XIL_AXI_INTC_CSR_DOWN_COUNT_MASK  0x00000002
+//#define XIL_AXI_INTC_CSR_CAPTURE_MODE_MASK  0x00000001
+
diff --git a/projects/lago_v1_3/src/globaldefs.h b/projects/lago_v1_3/src/globaldefs.h
new file mode 100644
index 0000000000000000000000000000000000000000..33b3ac5ac8dcfd53ba594b6df1168f2f7480845d
--- /dev/null
+++ b/projects/lago_v1_3/src/globaldefs.h
@@ -0,0 +1,20 @@
+#define  _CRT_SECURE_NO_WARNINGS
+
+#define _FILE_OFFSET_BITS  64
+
+#ifndef EXP
+#define EXP "LAGO"
+#endif
+
+/* Output format version */
+#define DATAVERSION 		5
+#define VERSION 				2
+#define REVISION	 			0
+
+#define MAXCHRLEN 			1024
+#define BLOCKSIZE				16384
+#define MAXFILENAMELEN	255
+#define MAXPRESS 				1100 //1100Hpa
+#define PRESSUREBLOCKSIZE	22
+#define GPSBLOCKSIZE 			64
+
diff --git a/projects/lago_v1_3/src/gps_rp.c b/projects/lago_v1_3/src/gps_rp.c
new file mode 100644
index 0000000000000000000000000000000000000000..708a69158fc59d6ab23c3f0ccd1d747aae8534e9
--- /dev/null
+++ b/projects/lago_v1_3/src/gps_rp.c
@@ -0,0 +1,96 @@
+#include "gps_rp.h"
+
+static double gps_deg_dec(double deg_point)
+{
+  double ddeg;
+  double sec = modf(deg_point, &ddeg)*60;
+  int deg = (int)(ddeg/100);
+  int min = (int)(deg_point-(deg*100));
+
+  double absdlat = round(deg * 1000000.);
+  double absmlat = round(min * 1000000.);
+  double absslat = round(sec * 1000000.);
+
+  return round(absdlat + (absmlat/60) + (absslat/3600)) /1000000;
+}
+
+// Convert lat and lon to decimals (from deg)
+static void gps_convert_deg_to_dec(double *latitude, char ns,  double *longitude, char we)
+{
+  double lat = (ns == 'N') ? *latitude : -1 * (*latitude);
+  double lon = (we == 'E') ? *longitude : -1 * (*longitude);
+
+  *latitude = gps_deg_dec(lat);
+  *longitude = gps_deg_dec(lon);
+}
+
+void gps_init(void) 
+{
+  rp_UartInit();
+  rp_UartConfig();
+}
+
+void gps_on(void) 
+{
+}
+
+// Compute the GPS location using decimal scale
+void gps_location(loc_t *coord) 
+{
+  uint8_t status = _EMPTY;
+  while(status != _COMPLETED) {
+    gpgga_t gpgga;
+    gprmc_t gprmc;
+    char buffer[256];
+
+    rp_UartReadln(buffer, 256);
+    switch (rp_NmeaGetMessageType(buffer)) {
+      case NMEA_GPGGA:
+        rp_NmeaParseGpgga(buffer, &gpgga);
+
+        gps_convert_deg_to_dec(&(gpgga.latitude), gpgga.lat, &(gpgga.longitude), gpgga.lon);
+
+        coord->times = gpgga.times;
+        coord->latitude = gpgga.latitude;
+        coord->longitude = gpgga.longitude;
+        coord->altitude = gpgga.altitude;
+        coord->satellites = gpgga.satellites;
+
+        status |= NMEA_GPGGA;
+        break;
+      case NMEA_GPRMC:
+        rp_NmeaParseGprmc(buffer, &gprmc);
+
+        coord->speed = gprmc.speed;
+        coord->course = gprmc.course;
+        coord->date = gprmc.date;
+
+        status |= NMEA_GPRMC;
+        break;
+    }
+  }
+}
+
+void gps_off(void) 
+{
+  //Write off
+  rp_UartClose();
+}
+
+int gps_print_data()
+{
+        gps_init();
+
+        loc_t data;
+
+        gps_location(&data);
+
+        printf("Time      : %06d\n",(uint32_t)data.times);
+        printf("Date      : %06d\n",(uint32_t)data.date);
+        printf("Latitude  : %lf\n", data.latitude);
+        printf("Longitude : %lf\n", data.longitude);
+        printf("Altitude  : %.1lf\n", data.altitude);
+        printf("Satellites: %d\n", (uint32_t)data.satellites);
+
+        return 0;
+}
diff --git a/projects/lago_v1_3/src/gps_rp.h b/projects/lago_v1_3/src/gps_rp.h
new file mode 100644
index 0000000000000000000000000000000000000000..046a852a76dce31a715548532618217f124fed0d
--- /dev/null
+++ b/projects/lago_v1_3/src/gps_rp.h
@@ -0,0 +1,28 @@
+#ifndef _GPS_RP_H_
+#define _GPS_RP_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "nmea_rp.h"
+#include "uart_rp.h"
+
+typedef struct location {
+    double times;
+    double date;
+    double latitude;
+    double longitude;
+    double speed;
+    double altitude;
+    double course;
+    double satellites;
+} loc_t;
+
+void gps_init(void);
+void gps_on(void);
+void gps_location(loc_t *);
+void gps_off(void);
+int  gps_print_data(void);
+
+#endif
diff --git a/projects/lago_v1_3/src/lago.c b/projects/lago_v1_3/src/lago.c
new file mode 100644
index 0000000000000000000000000000000000000000..bb1bf3c8ee1cbacc245c00abad92c58345a48a7e
--- /dev/null
+++ b/projects/lago_v1_3/src/lago.c
@@ -0,0 +1,1000 @@
+#include "lago.h"
+
+//*****************************************************
+// Pressure, temperature and other constants
+//****************************************************
+double  gps_lat,gps_lon,gps_alt;
+
+//Globals
+int interrupted = 0;
+int n_dev;
+uint32_t reg_off;
+int32_t reg_val;
+//double r_val;
+int limit;
+int current;
+loc_t g_data;
+// detector rates
+int r1,r2;
+// timing horrible hack
+int hack=0;
+
+int fReadReg, fGetCfgStatus, fGetPT, fGetGPS, fGetXADC, fInitSystem, fWriteReg, 
+		fSetCfgReg, fToFile, fToStdout, fFile, fCount, fByte, fRegValue, fData, 
+		fFirstTime=1,	fshowversion;
+
+char charAction[MAXCHRLEN], scRegister[MAXCHRLEN], charReg[MAXCHRLEN],
+		 charFile[MAXCHRLEN], charCurrentFile[MAXCHRLEN], charCount[MAXCHRLEN],
+		 scByte[MAXCHRLEN], charRegValue[MAXCHRLEN], charCurrentMetaData[MAXCHRLEN];
+
+//FILE        *fhin = NULL;
+FILE         *fhout = NULL;
+FILE         *fhmtd = NULL;
+struct FLContext  *handle = NULL;
+
+#ifdef FUTURE
+unordered_map<string, string> hConfigs;
+#endif
+
+//****************************************************
+// Time globals for filenames
+//****************************************************
+time_t    fileTime;
+struct tm *fileDate;
+int       falseGPS=0;
+
+//****************************************************
+// Metadata
+//****************************************************
+// Metadata calculations, dataversion v5 need them
+// average rates and deviation per trigger condition
+// average baseline and deviation per channel
+// using long int as max_rate ~ 50 kHz * 3600 s = 1.8x10^7 ~ 2^(20.5)
+// and is even worst for baseline
+#define MTD_TRG   8
+#define MTD_BL    3
+#define MTD_BLBIN 1
+//daq time
+int mtd_seconds=0;
+// trigger rates
+long int mtd_rates[MTD_TRG], mtd_rates2[MTD_TRG];
+//base lines
+long int mtd_bl[MTD_BL], mtd_bl2[MTD_BL];
+int mtd_iBin=0;
+long int mtd_cbl=0;
+// deat time defined as the number of missing pulses over the total number
+// of triggers. We can determine missing pulses as the sum of the differences 
+// between consecutive pulses
+long int mtd_dp = 0, mtd_cdp = 0, mtd_pulse_cnt = 0, mtd_pulse_pnt = 0;
+// and finally, a vector of strings to handle configs file. I'm also including a
+// hash table
+// for future implementations. For now, we just dump the lago-configs file
+//vector <string> configs_lines;
+int position;
+int main(int argc, char *argv[])
+{
+	int rc;
+	//PT device
+	float t, p, alt, volt;
+	char *i2c_device = "/dev/i2c-0";
+	int address = 0x77;
+
+	void *bmp = bmp180_init(address, i2c_device);
+
+	bmp180_eprom_t eprom;
+	bmp180_dump_eprom(bmp, &eprom);
+
+
+	bmp180_set_oss(bmp, 1);
+	//end PT device
+
+	pthread_t not_gps;
+	//pthread_t actual_gps;
+
+	//Check the arguments
+	if (!parse_param(argc, argv)) {
+		show_usage(argv[0]);
+		return 1;
+	}
+
+	//initialize devices. TODO: add error checking 
+	intc_init();    
+	cfg_init();    
+	sts_init();    
+	xadc_init();
+	cma_init();
+	//printf("dev_size es: %d ...\n",dev_size);
+	//printf("Set writer address...\n");
+	rd_reg_value(1, CFG_WR_ADDR_OFFSET,0);
+	//printf("dev_size es: %d ...\n",dev_size);
+	wr_reg_value(1, CFG_WR_ADDR_OFFSET, dev_size,0);
+
+	//Check if it is the first time we access the PL
+	//This is for initial configuration
+	//default is MASTER mode, using false PPS
+	if (dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET) == 0) //first time access
+	{
+		printf("Initializing registers...\n");
+		init_system();
+		//FIXME: here i should initialise my thread for working with false PPS
+		rc = pthread_create(&not_gps,NULL,thread_isr_not_gps,NULL);
+		if (rc != EXIT_SUCCESS) {
+			perror("pthread_create :: error \n");
+			exit(EXIT_FAILURE);
+		}
+
+		enable_interrupt();
+	}
+
+	//Ckeck if we should use GPS data or PC data
+	/*				if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 0) //ok, we should use GPS data
+						{
+						rc = pthread_create(&actual_gps,NULL,thread_isr,NULL);
+						if (rc != EXIT_SUCCESS) {
+						perror("pthread_create :: error \n");
+						exit(EXIT_FAILURE);
+						}
+
+						enable_interrupt();
+						}*/
+
+	signal(SIGINT, signal_handler);
+
+	if(fReadReg) {
+		rd_reg_value(n_dev, reg_off,1);  // Read single register
+	}
+	else if (fWriteReg) {
+		wr_reg_value(n_dev, reg_off, reg_val, 1);  // Write single register
+	}
+	else if (fSetCfgReg) {
+		if (fRegValue) set_voltage(reg_off, atoi(charRegValue)); // For HV, OV
+		else wr_reg_value(1,reg_off, atoi(charRegValue), 1);        // For t1, t2, st1, st2  
+	}
+	else if (fGetCfgStatus) {
+		rd_cfg_status();        // Get registers status
+	}
+	else if (fGetPT) {
+		if(bmp != NULL){
+			//int i;
+			//for(i = 0; i < 10; i++) {
+			t = bmp180_temperature(bmp);
+			p = bmp180_pressure(bmp);
+			alt = bmp180_altitude(bmp);
+			// Temperature in Celsius, Presure in HectoPascal and Altitude in meters
+			printf("Temperature = %.1f, Pressure = %.2f, Altitude= %.1f\n", t, p/100., alt);
+			//usleep(2 * 1000 * 1000);
+			//}
+
+			bmp180_close(bmp);
+		}else{
+			printf("Error! NO BMP device is present!\n");
+		}
+	}
+	else if (fGetGPS) { 
+		if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 1) { // No GPS is present
+			printf("No GPS device is present or enabled!!!\n");
+		}
+		else{
+			gps_print_data();     // Print GPS data to stdout 
+		}		
+	}
+	else if (fInitSystem) {
+		printf("Initializing registers...\n");
+		init_system();
+	}
+	else if (fGetXADC) {
+		printf("Reading XADC channels...\n");
+		printf("Voltage CH1: %.3f\n",get_voltage(XADC_AI0_OFFSET));
+		printf("Voltage CH2: %.3f\n",get_voltage(XADC_AI1_OFFSET));
+		volt = get_voltage(XADC_AI2_OFFSET);
+		printf("Voltage CH3: %.3f V (%.1f V)\n",volt, (volt/0.0031949));
+		volt = get_voltage(XADC_AI3_OFFSET);
+		printf("Voltage CH4: %.3f V (%.1f V)\n",volt, (volt/0.0031949));
+		printf("Base temperature CH1: %.1f ºC\n",get_temp_AD592(XADC_AI0_OFFSET));
+		printf("Base temperature CH2: %.1f ºC\n",get_temp_AD592(XADC_AI1_OFFSET));
+
+	}
+	else if (fToFile || fToStdout) {
+
+		limit = 1024*1024; // whole memory
+		current = -2; // new readout system, hack due to using +4 for readout
+		// enter normal mode for tlast_gen
+		reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+		dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 2);
+		// enter normal mode for pps_gen, fifo and trigger modules
+		reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+		dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 1);
+		// enter normal mode for data converter and writer
+		reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+		dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 4);
+
+		//FIXME: here we should enable interrupts 
+		while(!interrupted){
+			// alarm(2);   // setting 1 sec timeout
+			// read writer position 
+			//position = dev_read(sts_ptr, STS_STATUS_OFFSET); 
+			wait_for_interrupt(intc_fd, intc_ptr);
+			read_buffer(position, bmp);
+			// alarm(0);   // cancelling 1 sec timeout
+		}
+		// reset pps_gen, fifo and trigger modules
+		reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+		dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~1);
+		/* reset data converter and writer */
+		reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+		dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~4);
+		// enter reset mode for tlast_gen
+		reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+		dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~2);
+
+	}
+
+	// unmap and close the devices 
+	munmap(intc_ptr, sysconf(_SC_PAGESIZE));
+	munmap(cfg_ptr, sysconf(_SC_PAGESIZE));
+	munmap(sts_ptr, sysconf(_SC_PAGESIZE));
+	munmap(xadc_ptr, sysconf(_SC_PAGESIZE));
+	//munmap(mem_ptr, sysconf(_SC_PAGESIZE));
+
+	close(intc_fd);
+	close(cfg_fd);
+	close(sts_fd);
+	close(xadc_fd);
+
+	return 0;
+
+}
+
+void signal_handler(int sig)
+{
+	interrupted = 1;
+}
+
+int wait_for_interrupt(int fd_int, void *dev_ptr) 
+{
+	uint32_t value;
+	uint32_t info = 1; /* unmask */
+
+	ssize_t nb = write(fd_int, &info, sizeof(info));
+	if (nb != (ssize_t)sizeof(info)) {
+		perror("write");
+		close(fd_int);
+		exit(EXIT_FAILURE);
+	}
+
+	// block (timeout for poll) on the file waiting for an interrupt 
+	struct pollfd fds = 
+	{
+		.fd = fd_int,
+		.events = POLLIN,
+	};
+
+	int ret = poll(&fds, 1, 1000);
+	//printf("ret is : %d\n", ret);
+	if (ret >= 1) {
+		nb = read(fd_int, &info, sizeof(info));
+		if (nb == (ssize_t)sizeof(info)) {
+			/* Do something in response to the interrupt. */
+			value = dev_read(dev_ptr, XIL_AXI_INTC_IPR_OFFSET);
+			if ((value & 0x00000001) != 0) {
+				dev_write(dev_ptr, XIL_AXI_INTC_IAR_OFFSET, 1);
+				// read writer position 
+				position = dev_read(sts_ptr, STS_STATUS_OFFSET);
+
+			}
+		} else {
+			perror("poll()");
+			close(fd_int);
+			exit(EXIT_FAILURE);
+		}
+	}
+	return ret;
+}
+
+void *thread_isr(void *p) 
+{
+	int32_t g_tim, g_dat, g_lat, g_lon, g_alt, g_sat;
+	//initialize GPS connection
+	gps_init();
+	while(1)
+		if (wait_for_interrupt(intc_fd, intc_ptr)){
+			//get GPS data
+			gps_location(&g_data);
+			//write GPS data into registers
+			//FIXME: see how and where to write pressure and temperature data
+			// convert float to int32_t to write to FPGA
+			g_tim = (int32_t)(g_data.times); 
+			g_dat = (int32_t)(g_data.date); 
+			g_lat = (int32_t)(g_data.latitude * 65536);
+			g_lon = (int32_t)(g_data.longitude * 65536);
+			g_alt = (int32_t)(g_data.altitude * 65536);
+			g_sat = (int32_t)(g_data.satellites); 
+
+			dev_write(cfg_ptr,CFG_TIME_OFFSET, g_tim);
+			dev_write(cfg_ptr,CFG_DATE_OFFSET, g_dat);
+			dev_write(cfg_ptr,CFG_LATITUDE_OFFSET, g_lat);
+			dev_write(cfg_ptr,CFG_LONGITUDE_OFFSET, g_lon);
+			dev_write(cfg_ptr,CFG_ALTITUDE_OFFSET, g_alt);
+			dev_write(cfg_ptr,CFG_SATELLITE_OFFSET, g_sat);
+			//printf("%lf %lf\n", gps_data.latitude, gps_data.longitude);
+		}
+}
+
+void *thread_isr_not_gps(void *p) 
+{
+	//int32_t g_tim, g_dat, g_lat, g_lon, g_alt, g_sat;
+	while(1)
+		if (wait_for_interrupt(intc_fd, intc_ptr)){
+			//write GPS data into registers
+			//FIXME: see how and where to write pressure and temperature data
+			// convert float to int32_t to write to FPGA
+			/*g_tim = (int32_t)(g_data.times); 
+				g_dat = (int32_t)(g_data.date); 
+				g_lat = (int32_t)(g_data.latitude * 65536);
+				g_lon = (int32_t)(g_data.longitude * 65536);
+				g_alt = (int32_t)(g_data.altitude * 65536);
+				g_sat = (int32_t)(g_data.satellites); 
+
+				dev_write(cfg_ptr,CFG_TIME_OFFSET, g_tim);
+				dev_write(cfg_ptr,CFG_DATE_OFFSET, g_dat);
+				dev_write(cfg_ptr,CFG_LATITUDE_OFFSET, g_lat);
+				dev_write(cfg_ptr,CFG_LONGITUDE_OFFSET, g_lon);
+				dev_write(cfg_ptr,CFG_ALTITUDE_OFFSET, g_alt);
+				dev_write(cfg_ptr,CFG_SATELLITE_OFFSET, g_sat);
+				*/
+			//printf("%lf %lf\n", gps_data.latitude, gps_data.longitude);
+		}
+}
+
+void show_usage(char *progname) 
+{
+	if (fshowversion) {
+		printf("LAGO ACQUA BRC v%dr%d data v%d\n",VERSION,REVISION,DATAVERSION);
+	} else {
+		printf("\n\tThe LAGO ACQUA suite\n");
+		printf("\tData acquisition system for the LAGO BRC electronic\n");
+		printf("\t(c) 2012-Today, The LAGO Project, http://lagoproject.net\n");
+		printf("\t(c) 2012, LabDPR, http://labdpr.cab.cnea.gov.ar\n");
+		printf("\n\tThe LAGO Project, lago@lagoproject.org\n");
+		printf("\n\tDPR Lab. 2021\n");
+		printf("\tH. Arnaldi, lharnaldi@gmail.com\n");
+		printf("\tX. Bertou, bertou@gmail.com\n");
+		printf("\t%s v%dr%d comms soft\n\n",EXP,VERSION,REVISION);
+		printf("Usage: %s <action> <register> <value> [options]\n", progname);
+
+		printf("\n\tActions:\n");
+		//  printf("\t-r\t\t\t\tGet a single register value\n");
+		//  printf("\t-p\t\t\t\tSet a value into a single register\n");
+		printf("\t-a\t\t\t\tGet all registers status\n");
+		printf("\t-s\t\t\t\tSet registers\n");
+		printf("\t-f\t\t\t\tStart DAQ and save data to file\n");
+		printf("\t-o\t\t\t\tStart DAQ and send data to stdout\n");
+		printf("\t-g\t\t\t\tGet GPS data\n");
+		printf("\t-t\t\t\t\tGet Pressure and Temperature data\n");
+		printf("\t-i\t\t\t\tInitialise registers to default values\n");
+		printf("\t-x\t\t\t\tRead the voltage in the XADC channels\n");
+		printf("\t-v\t\t\t\tShow DAQ version\n");
+
+		printf("\n\tRegisters:\n");
+		printf("\tt1, t2\t\t\t\tSpecify triggers 1 and 2\n");
+		printf("\tsc1, sc2\t\t\tSpecify scaling factor 1 and 2\n");
+		//printf("\tst1, st2, st3\t\t\tSpecify subtriggers 1, 2 and
+		//3\n");
+		printf("\thv1, hv2\t\t\tSpecify high voltages\n");
+		printf("\tov1, ov2, ov3, ov4\t\tSpecify output voltages\n");
+		//printf("\tiv1, iv2, iv3, iv4\t\t\tRead input voltages\n");
+
+		printf("\n\tOptions:\n");
+		printf("\t-f <filename>\t\t\tSpecify file name\n");
+		//printf("\t-c <# bytes>\t\t\tNumber of bytes to read/write\n");
+		//printf("\t-b <byte>\t\t\tValue to load into register\n");
+
+		printf("\n\n");
+	}
+}
+
+//TODO: change this function to just strncpy
+void StrcpyS(char *szDst, size_t cchDst, const char *szSrc) 
+{
+
+#if defined (WIN32)     
+
+	strcpy_s(szDst, cchDst, szSrc);
+
+#else
+
+	if ( 0 < cchDst ) {
+
+		strncpy(szDst, szSrc, cchDst - 1);
+		szDst[cchDst - 1] = '\0';
+	}
+
+#endif
+}      
+
+int parse_param(int argc, char *argv[]) 
+{
+
+	int    arg;
+
+	// Initialize default flag values 
+	fReadReg    = 0;
+	fWriteReg    = 0;
+	fGetCfgStatus = 0;
+	fSetCfgReg = 0;
+	fToFile    = 0;
+	fToStdout  = 0;
+	fGetPT     = 0;
+	fGetGPS    = 0;
+	fFile      = 0;
+	fCount     = 0;
+	fByte      = 0;
+	fData      = 0;
+	fRegValue  = 0;
+	fGetXADC   = 0;
+
+	// Ensure sufficient paramaters. Need at least program name and action
+	// flag
+	if (argc < 2) 
+	{
+		return 0;
+	}
+
+	// The first parameter is the action to perform. Copy the first
+	// parameter into the action string.
+	StrcpyS(charAction, MAXCHRLEN, argv[1]);
+	if(strcmp(charAction, "-r") == 0) {
+		fReadReg = 1;
+	} 
+	else if( strcmp(charAction, "-w") == 0) {
+		fWriteReg = 1;
+	} 
+	else if( strcmp(charAction, "-a") == 0) {
+		fGetCfgStatus = 1;
+		return 1;
+	} 
+	else if( strcmp(charAction, "-v") == 0) {
+		fshowversion = 1;
+		return 0;
+	} 
+	else if( strcmp(charAction, "-s") == 0) {
+		fSetCfgReg = 1;
+	} 
+	else if( strcmp(charAction, "-f") == 0) {
+		fToFile = 1;
+	} 
+	else if( strcmp(charAction, "-o") == 0) {
+		fToStdout = 1;
+		return 1;
+	} 
+	else if( strcmp(charAction, "-t") == 0) {
+		fGetPT = 1;
+		return 1;
+	} 
+	else if( strcmp(charAction, "-g") == 0) {
+		fGetGPS = 1;
+		return 1;
+	} 
+	else if( strcmp(charAction, "-i") == 0) {
+		fInitSystem = 1;
+		return 1;
+	} 
+	else if( strcmp(charAction, "-x") == 0) {
+		fGetXADC = 1;
+		return 1;
+	} 
+	else { // unrecognized action
+		return 0;
+	}
+
+	// Second paramater is target register on device. Copy second paramater
+	// to the register string
+	if((fReadReg == 1) || (fWriteReg == 1)) {
+		StrcpyS(charReg, MAXCHRLEN, argv[2]);
+		if(strcmp(charReg, "intc") == 0) {
+			n_dev = 0; 
+		} 
+		else if(strcmp(charReg, "cfg") == 0) {
+			n_dev = 1; 
+		} 
+		else if(strcmp(charReg, "sts") == 0) {
+			n_dev = 2; 
+		} 
+		else if(strcmp(charReg, "xadc") == 0) {
+			n_dev = 3; 
+		}
+		else { // unrecognized device to set
+			return 0;
+		}
+		reg_off = strtoul(argv[3],NULL, 16);
+		//FIXME: see if this can be done better
+		if (fWriteReg) reg_val = strtoul(argv[4],NULL,16);
+		return 1;
+	}
+
+	else if(fSetCfgReg) {
+		StrcpyS(charReg, MAXCHRLEN, argv[2]);
+		// Registers for Triggers
+		if(strcmp(charReg, "t1") == 0) {
+			reg_off = CFG_TRLVL_1_OFFSET;
+		} 
+		else if(strcmp(charReg, "t2") == 0) {
+			reg_off = CFG_TRLVL_2_OFFSET;
+		} 
+		// Registers for Subtriggers
+		else if(strcmp(charReg, "st1") == 0) {
+			reg_off = CFG_STRLVL_1_OFFSET;
+		} 
+		else if(strcmp(charReg, "st2") == 0) {
+			reg_off = CFG_STRLVL_2_OFFSET;
+		} 
+		// Registers for High Voltage
+		else if(strcmp(charReg, "hv1") == 0) {
+			reg_off = CFG_HV1_OFFSET;
+		} 
+		else if(strcmp(charReg, "hv2") == 0) {
+			reg_off = CFG_HV2_OFFSET;
+		} 
+		// Registers for output voltages
+		else if(strcmp(charReg, "ov1") == 0) {
+			reg_off = CFG_HV1_OFFSET;
+		} 
+		else if(strcmp(charReg, "ov2") == 0) {
+			reg_off = CFG_HV2_OFFSET;
+		} 
+		else if(strcmp(charReg, "ov3") == 0) {
+			reg_off = CFG_HV3_OFFSET;
+		} 
+		else if(strcmp(charReg, "ov4") == 0) {
+			reg_off = CFG_HV4_OFFSET;
+		} 
+		// Registers for scalers
+		else if(strcmp(charReg, "sc1") == 0) {
+			reg_off = CFG_TR_SCAL_A_OFFSET;
+		} 
+		else if(strcmp(charReg, "sc2") == 0) {
+			reg_off = CFG_TR_SCAL_B_OFFSET;
+		} 
+		// Unrecognized
+		else { // unrecognized register to set
+			return 0;
+		}
+		//charCount[0] = '4';
+		//fCount = 1;
+		StrcpyS(charRegValue, 16, argv[3]);
+		if((strncmp(charReg, "hv", 2) == 0) || (strncmp(charReg, "ov", 2) == 0)) {
+			if (atoi(charRegValue)>2500) {
+				printf ("Error: maximum voltage is 2500 mV\n");
+				exit(1);
+			}
+			fRegValue = 1;
+		}
+		//fData = 1; FIXME: not used apparently
+	} 
+	else if(fToFile) {
+		if(argv[2] != NULL) {
+			StrcpyS(charFile, MAXFILENAMELEN, argv[2]);
+			fFile = 1;
+		} 
+		else {
+			return 0;
+		}
+	} 
+	else {
+		StrcpyS(scRegister, MAXCHRLEN, argv[2]);
+
+		// Parse the command line parameters.
+		arg = 3;
+		while(arg < argc) {
+
+			// Check for the -f parameter used to specify the
+			// input/output file name.
+			if (strcmp(argv[arg], "-f") == 0) {
+				arg += 1;
+				if (arg >= argc) {
+					return 0;
+				}
+				StrcpyS(charFile, 16, argv[arg++]);
+				fFile = 1;
+			}
+
+			// Check for the -c parameter used to specify the number
+			// of bytes to read/write from file.
+			else if (strcmp(argv[arg], "-c") == 0) {
+				arg += 1;
+				if (arg >= argc) {
+					return 0;
+				}
+				StrcpyS(charCount, 16, argv[arg++]);
+				fCount = 1;
+			}
+
+			// Check for the -b paramater used to specify the value
+			// of a single data byte to be written to the register 
+			else if (strcmp(argv[arg], "-b") == 0) {
+				arg += 1;
+				if (arg >= argc) {
+					return 0;
+				}
+				StrcpyS(scByte, 16, argv[arg++]);
+				fByte = 1;
+			}
+
+			// Not a recognized parameter
+			else {
+				return 0;
+			}
+		} // End while
+
+		// Input combination validity checks 
+		if( fWriteReg && !fByte ) {
+			printf("Error: No byte value provided\n");
+			return 0;
+		}
+		if( (fToFile ) && !fFile ) {
+			printf("Error: No filename provided\n");
+			return 0;
+		}
+
+		return 1;
+	}
+	return 1;
+}
+
+int new_file() 
+{
+	char buf[256];
+	time_t currt=time(NULL);
+	//uint32_t i;
+
+	if (!fToStdout) {
+		if (fhout) {
+			fclose(fhout);
+		}
+		/*if (fhmtd) {
+		//before to close the file we have to fill DAQ status metadata
+		// Average and deviation trigger rates
+		double mtd_avg[MTD_TRG], mtd_dev[MTD_TRG];
+		if (!mtd_seconds) {
+		for (int i=0; i<MTD_TRG; i++)
+		mtd_avg[i] = mtd_dev[i] = -1.;
+		} 
+		else {
+		for (int i=0; i<MTD_TRG; i++) {
+		mtd_avg[i] = 1. * mtd_rates[i] / mtd_seconds;
+		mtd_dev[i] = sqrt(1. * mtd_rates2[i] / mtd_seconds - mtd_avg[i] * mtd_avg[i]);
+		}
+		}
+		for (int i=1; i<MTD_TRG; i++)
+		fprintf(fhmtd, "triggerRateAvg%02d=%lf\n", i, mtd_avg[i]);
+		for (int i=1; i<MTD_TRG; i++)
+		fprintf(fhmtd, "trigggerRateDev%02d=%lf\n", i, mtd_dev[i]);
+		for (int i=0; i<MTD_TRG; i++)
+		mtd_rates[i] = mtd_rates2[i] = 0;
+		//baselines
+		double mtd_bl_avg[MTD_BL], mtd_bl_dev[MTD_BL];
+		double mtd_cdpf;
+		if (!mtd_cbl) {
+		for (int i=0; i<MTD_BL; i++)
+		mtd_bl_avg[i] = mtd_bl_dev[i] = -1.;
+		mtd_cdpf = -1;
+		} 
+		else {
+		for (int i=0; i<MTD_BL; i++) {
+		mtd_bl_avg[i] = 1. * mtd_bl[i] / mtd_cbl;
+		mtd_bl_dev[i] = sqrt(1. * mtd_bl2[i] / mtd_cbl - mtd_bl_avg[i] * mtd_bl_avg[i]);
+		}
+		mtd_cdpf = 1. * mtd_cdp / mtd_cbl;
+		}
+		for (int i=1; i<MTD_BL; i++)
+		fprintf(fhmtd, "baselineAvg%02d=%lf\n", i+1, mtd_bl_avg[i]);
+		for (int i=1; i<MTD_BL; i++)
+		fprintf(fhmtd, "baselineDev%02d=%lf\n", i+1, mtd_bl_dev[i]);
+		for (int i=0; i<MTD_BL; i++)
+		mtd_bl[i] = mtd_bl2[i] = 0;
+		// daq time, pulses and dead time
+		fprintf(fhmtd, "daqTime=%d\n", mtd_seconds);
+		fprintf(fhmtd, "totalPulses=%ld\n", mtd_cbl);
+		fprintf(fhmtd, "totalPulsesLost=%ld\n", mtd_cdp);
+		fprintf(fhmtd, "fractionPulsesLost=%le\n", mtd_cdpf);
+		//and now, let's close the file
+		mtd_seconds = 0;
+		mtd_cbl = mtd_cdp = 0;
+		fclose(fhmtd);
+		}*/
+		fileTime=timegm(fileDate);
+		fileDate=gmtime(&fileTime); // filling all fields with properly computed values (for new month/year)
+		if (falseGPS) {
+			snprintf(charCurrentFile,MAXCHRLEN,"%s_nogps_%04d_%02d_%02d_%02dh00.dat",charFile,fileDate->tm_year+1900, fileDate->tm_mon+1,fileDate->tm_mday,fileDate->tm_hour);
+			snprintf(charCurrentMetaData,MAXCHRLEN,"%s_nogps_%04d_%02d_%02d_%02dh00.mtd",charFile,fileDate->tm_year+1900, fileDate->tm_mon+1,fileDate->tm_mday,fileDate->tm_hour);
+		} 
+		else {
+			snprintf(charCurrentFile,MAXCHRLEN,"%s_%04d_%02d_%02d_%02dh00.dat",charFile,fileDate->tm_year+1900, fileDate->tm_mon+1,fileDate->tm_mday,fileDate->tm_hour);
+			snprintf(charCurrentMetaData,MAXCHRLEN,"%s_%04d_%02d_%02d_%02dh00.mtd",charFile,fileDate->tm_year+1900, fileDate->tm_mon+1,fileDate->tm_mday,fileDate->tm_hour);
+		}
+		fhout = fopen(charCurrentFile, "ab");
+		//fhmtd = fopen(charCurrentMetaData, "w");
+		//fprintf(stderr,"Opening files %s and %s for data taking\n",charCurrentFile, charCurrentMetaData);
+		fprintf(stderr,"Opening file %s at %02dh%02d for data taking\n",charCurrentFile,fileDate->tm_hour,fileDate->tm_min);
+	}
+	fprintf(fhout,"# v %d\n", DATAVERSION);
+	fprintf(fhout,"# #\n");
+	fprintf(fhout,"# # This is a %s raw data file, version %d\n",EXP,DATAVERSION);
+	fprintf(fhout,"# # It contains the following data:\n");
+	fprintf(fhout,"# #   <N1> <N2>        : line with values of the 2 ADC for a triggered pulse\n");
+	//fprintf(fhout,"# #                      it is a subtrigger with the pulse maximum bin if only one such line is found\n");
+	//fprintf(fhout,"# #                      it is a trigger with the full pulse if 16 lines are found\n");
+	fprintf(fhout,"# #   # t <C> <V>      : end of a trigger\n");
+	fprintf(fhout,"# #                      gives the channel trigger (<C>: 3 bit mask) and 125 MHz clock count (<V>) of the trigger time\n");
+	fprintf(fhout,"# #   # c <C>          : internal trigger counter\n");
+	fprintf(fhout,"# #   # x f <V>        : 125 MHz frequency\n");
+	fprintf(fhout,"# #   # x t <V>        : temperature value\n");
+	fprintf(fhout,"# #   # x p <V>        : pressure value\n");
+	fprintf(fhout,"# #   # x r1 <V>       : pulse rate at channel 1\n");
+	fprintf(fhout,"# #   # x r2 <V>       : pulse rate at channel 2\n");
+	fprintf(fhout,"# #   # x h <HH:MM:SS> <DD/MM/YYYY> <S> : GPS time (every new second, last number is seconds since EPOCH)\n");
+	fprintf(fhout,"# #   # x s <T> C <P> hPa <A> m : temperature <T>, pressure <P> and altitude (from pressure) <A>\n");
+	fprintf(fhout,"# #   # x g <LAT> <LON> <ALT>   : GPS data - latitude, longitude, altitude\n");
+	fprintf(fhout,"# #   # x v <HV1> <HV2>         : HV voltages for channels 1 and 2\n");
+	fprintf(fhout,"# #   # x b <B1> <B2> <B3>      : baselines (NOT IMPLEMENTED IN LAGO)\n");
+	fprintf(fhout,"# # In case of error, an unfinished line will be finished by # E @@@\n");
+	fprintf(fhout,"# # Followed by a line with # E <N> and the error message in human readable format, where <N> is the error code:\n");
+	fprintf(fhout,"# #   # E 1 : read timeout of 2 seconds\n");
+	fprintf(fhout,"# #   # E 2 : too many buffer reading tries\n");
+	fprintf(fhout,"# #   # E 3 : unknown word from FPGA\n");
+	fprintf(fhout,"# #\n");
+	fprintf(fhout,"# # Current registers setting\n");
+	fprintf(fhout,"# #\n");
+	// Save settings into file
+	fprintf(fhout,"# x c T1 %d\n",dev_read(cfg_ptr, CFG_TRLVL_1_OFFSET));
+	fprintf(fhout,"# x c T2 %d\n",dev_read(cfg_ptr, CFG_TRLVL_2_OFFSET));
+	{
+		//float a = 0.0382061, b = 4.11435;  // For gain = 1.45
+		float a = 0.0882006, b = 7.73516;  // For gain = 3.2
+		fprintf(fhout,"# x c HV1 %.1f mV\n",a*dev_read(cfg_ptr, CFG_HV1_OFFSET)+b);
+		fprintf(fhout,"# x c HV2 %.1f mV\n",a*dev_read(cfg_ptr, CFG_HV2_OFFSET)+b);
+	}
+	fprintf(fhout,"# x c SC1 %d\n",dev_read(cfg_ptr, CFG_TR_SCAL_A_OFFSET));
+	fprintf(fhout,"# x c SC2 %d\n",dev_read(cfg_ptr, CFG_TR_SCAL_B_OFFSET));
+	gethostname(buf, 256);
+	fprintf(fhout,"# # This file was started on %s\n",buf);
+	//				fprintf(fhmtd, "daqHost=\"%s\"\n",buf);
+	ctime_r(&currt,buf);
+	fprintf(fhout,"# # Machine local time was %s",buf);
+	strtok(buf, "\n");
+	//				fprintf(fhmtd, "machineTime=\"%s\"\n",buf);
+	if (falseGPS) fprintf(fhout,"# # WARNING, there is no GPS, using PC time\n");
+	fprintf(fhout,"# #\n");
+	//				fprintf(fhmtd, "dataFile=\"%s\"\n",charCurrentFile);
+	//				fprintf(fhmtd, "metadataFile=\"%s\"\n",charCurrentMetaData);
+	//				fprintf(fhmtd, "daqVersion=%d\n",VERSION);
+	//				fprintf(fhmtd, "daqUseGPS=%s", (!falseGPS)?"true":"false");
+	//				fprintf(fhmtd, "dataVersion=%d\n",DATAVERSION);
+	//				for (i=0; i<configs_lines.size(); i++)
+	//								fprintf(fhmtd, "%s\n", configs_lines[i].c_str());
+	//				fprintf(fhmtd, "version=\"LAGO ACQUA BRC v%dr%d data v%d\"\n",VERSION,REVISION,DATAVERSION);
+	fflush(fhout);
+	//				fflush(fhmtd);
+	return 0;
+}
+
+int r[MTD_TRG];
+
+int read_buffer(int pos, void *bmp)
+{
+	uint32_t wo;
+	int16_t ch[2];
+	//uint32_t i, j;
+	uint32_t i;
+	//int offset;
+	int trig;
+	//int32_t v_temp;
+	int readinit=0;
+	int readend=limit;
+
+	if (fToStdout)
+		fhout=stdout;
+	if (fFirstTime) {
+		// if no GPS 
+		if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 1) { // get time form PC
+			fileTime=time(NULL);
+			fileDate=gmtime(&fileTime); // filling all fields
+			falseGPS=1;
+		} 
+		else {
+			fileTime=time(NULL);
+			fileDate=gmtime(&fileTime);
+			//FIXME: fill with actual data
+			fileDate->tm_sec=55;
+			fileDate->tm_min=55;
+			fileDate->tm_hour=10;
+			fileDate->tm_mday=29;
+			fileDate->tm_mon=8;
+			fileDate->tm_year=2018;
+
+			fileTime=timegm(fileDate);
+			fileDate=gmtime(&fileTime); // filling all fields
+		}
+		if (fhout != stdout) {
+			//FIXME: here read PyT data
+
+		}
+		new_file();
+		fFirstTime=0;
+	}
+
+	// pos is the number of 8 bytes word written. I need the memory
+	// location... Therefore, pos=pos*8
+	//pos=pos*4;
+
+	//printf("%d %d %d\n",current,pos,limit);
+	//fprintf(fhout,"# XB %d %d %d\n", current,pos,limit);
+	// print 512 IN1 and IN2 samples if ready, otherwise sleep 1 ms
+	// compare current writing location (pos) with previous (limit)
+	// if current<pos, then read from current to pos and adjust current
+	// if current>pos, then read from current to end of buffer and set current to 0 at the end
+	if (current==limit-2) current=-2; // hack, because I do +4 next to read from next position
+	if (current<pos+2) {
+		readinit=current+2;
+		readend=pos;
+	} else if (current>pos) {
+		readinit=current+2;
+		readend=limit; // note: don't read after limit
+	}
+	if(current!=pos) {
+
+		//printf("# # # # NEW BUFFER %d %d %d %d %d \n", readinit, readend, current, pos, limit);
+		//offset = limit > 0 ? 0 : 4096*1024;
+		//limit = limit > 0 ? 0 : 512*1024;
+
+		//for(i = readinit; i < readend; i+=4) {
+		for(i = readinit; i < readend; i++) {
+			ch[0] = *((cma_ptr + 2*i + 0));
+			ch[1] = *((cma_ptr + 2*i + 1));
+			//printf("%5d %5d\n", ch[0], ch[1]);
+			wo = *((uint32_t *)(cma_ptr + 2*i));
+			if (wo>>30==0) {
+				fprintf(fhout,"%5hd %5hd\n", (((ch[0]>>13)<<14) + ((ch[0]>>13)<<15) + ch[0]),(((ch[1]>>13)<<14) + ((ch[1]>>13)<<15) + ch[1]));
+				mtd_iBin++;
+				if (mtd_iBin == MTD_BLBIN) {
+					mtd_bl[0] += ch[0];
+					mtd_bl2[0] += ch[0] * ch[0];
+					mtd_bl[1] += ch[1];
+					mtd_bl2[1] += ch[1] * ch[1];
+					mtd_cbl++;
+				}
+			} 
+			else {
+				if (wo>>30==1) { //get trigger status and counter between PPS
+					fprintf(fhout,"# t %d %d\n", (wo>>27)&0x7, wo&0x7FFFFFF);
+					trig=(wo>>27)&0x7;
+					r[trig]++;
+					mtd_iBin=0;
+				} 
+				else {
+					if (wo>>30==2) {//get counter status
+						mtd_pulse_pnt = mtd_pulse_cnt;
+						mtd_pulse_cnt = (wo&0x3FFFFFFF);
+						mtd_dp = (mtd_pulse_cnt - mtd_pulse_pnt - 1);
+						if (mtd_dp > 0 && mtd_pulse_pnt)
+							mtd_cdp += mtd_dp;
+						fprintf(fhout,"# c %ld\n", mtd_pulse_cnt);
+					} 
+					else {
+						switch(wo>>27) {
+							case 0x18:
+								fprintf(fhout,"# x f %d \n", wo&0x07FFFFFF);//PPS counter
+								break;
+							case 0x19:
+								fprintf(fhout,"# x t %.1f \n", bmp180_temperature(bmp));
+								break;
+							case 0x1A:
+								fprintf(fhout,"# x p %.2f \n", (bmp180_pressure(bmp)/100.));
+								break;
+							case 0x1B:
+								if(falseGPS) {
+									fileDate->tm_sec++;
+									if (fileDate->tm_sec==60 && fileDate->tm_min==59) { // new hour
+										if (!fToStdout)
+											new_file();
+									} 
+									else {
+										fileTime=timegm(fileDate);
+										fileDate=gmtime(&fileTime); // filling all fields with properly comupted values (for new month/year)
+									}
+								} 
+								else {
+									if ((uint32_t)fileDate->tm_hour!=((wo>>16)&0x000000FF)) {
+										// new hour of data
+										if ((uint32_t)fileDate->tm_hour>((wo>>16)&0x000000FF)) { // new day
+											fileDate->tm_mday++;
+										}
+										fileDate->tm_hour=(wo>>16)&0x000000FF;
+										if (!fToStdout)
+											new_file();
+									}
+									fileDate->tm_hour=(wo>>16)&0x000000FF;
+									fileDate->tm_min=(wo>>8)&0x000000FF;
+									fileDate->tm_sec=wo&0x000000FF;
+								}
+								mtd_seconds++;
+								fileTime=timegm(fileDate);
+								fileDate=gmtime(&fileTime); // filling all fields with properly computed values (for new month/year)
+								fprintf(fhout,"# x h   %02d:%02d:%02d %02d/%02d/%04d %d %d\n",
+										fileDate->tm_hour, fileDate->tm_min, fileDate->tm_sec,
+										fileDate->tm_mday, fileDate->tm_mon+1,fileDate->tm_year+1900,
+										(int)fileTime,wo&0x03FFFFFF
+										);
+								fprintf(fhout,"# x v %.1f %.1f\n",(get_voltage(XADC_AI2_OFFSET)/0.0031949),(get_voltage(XADC_AI3_OFFSET)/0.0031949));
+								fprintf(fhout,"# p %u %.1f %.1f\n",hack++,get_temp_AD592(XADC_AI0_OFFSET),get_temp_AD592(XADC_AI1_OFFSET));
+								if (hack%60==0) printf("\n");
+								printf("rates %5d %5d, PPS %u        \r",r1,r2,hack);
+								fflush(stdout);
+								/*fprintf(stderr,"# %02d:%02d:%02d %02d/%02d/%04d %d - second %d - rates: %d %d %d (%d - %d - %d) [%d]\r", 
+									fileDate->tm_hour, fileDate->tm_min, fileDate->tm_sec,
+									fileDate->tm_mday, fileDate->tm_mon+1, fileDate->tm_year+1900,
+									(int)fileTime,
+									mtd_seconds,
+									r[1], r[2], r[4], r[3], r[5], r[6], r[7]
+									);*/
+								//for (j=0; j<MTD_TRG; j++) {
+								//				mtd_rates[i] += r[i];
+								//				mtd_rates2[i] += r[i] * r[i];
+								//				r[i] = 0;
+								//}
+								break;
+								//FIXME: see if can add the FPGA interface in this stage
+							case 0x1C: // Longitude, latitude, defined by other bits
+								switch(((wo)>>24) & 0x7) {
+									case 0:
+										gps_lat=((int32_t)(wo&0xFFFFFF)<<8>>8)/65536.0;
+										//gps_lat=v_temp/65536.0;
+										break;
+									case 1:
+										gps_lon=((int32_t)(wo&0xFFFFFF)<<8>>8)/65536.0;
+										//gps_lat=v_temp/65536.0;
+										break;
+									case 2:
+										gps_alt=((int32_t)(wo&0xFFFFFF)<<8>>8)/65536.0;
+										//gps_lat=v_temp/65536.0;
+										//fprintf(fhout,"# x g %.6f %.6f %.2f\n",gps_lat,gps_lon,gps_alt);
+										fprintf(fhout,"# x g %.6f %.6f %.2f\n",g_data.latitude,g_data.longitude,g_data.altitude);
+										//tmp_gps_lon=((wo & 0xFFFFFF)<<8);
+										break;
+										/*case 3: FIXME: here is the date data
+										// Not used here
+										//gps_lon=((int)(tmp_gps_lon+(wo & 0xFF)))/3600000.;
+										break;
+										case 4:
+										//tmp_gps_elips=((wo & 0xFFFFFF)<<8);
+										break;
+										case 5:
+										//gps_elips=((int)(tmp_gps_elips+(wo & 0xFF)))/100.;
+										//fprintf(fhout,"# x g %.6f %.6f %.2f\n",gps_lat,gps_lon,gps_elips);
+										break;*/
+									default:
+										break;
+								}
+								break;
+							case 0x1D: //rate ch1 counter
+								fprintf(fhout,"# r1 %d \n", (int32_t)wo&0x00FFFFFF);
+								r1= (int32_t)wo&0x00FFFFFF;
+								break;
+							case 0x1E: //rate ch2 counter
+								fprintf(fhout,"# r2 %d \n", (int32_t)wo&0x00FFFFFF);
+								r2= (int32_t)wo&0x00FFFFFF;
+								break;
+							default:
+								fprintf(fhout,"# E @@@\n");
+								fprintf(fhout,"# E 3 - unknown word from FPGA: %d %x\n",wo>>27,wo>>27);
+								break;
+						}
+					}
+				}
+			}
+			current=i;
+		}
+	}
+	return 1;
+}
+
diff --git a/projects/lago_v1_3/src/lago.h b/projects/lago_v1_3/src/lago.h
new file mode 100644
index 0000000000000000000000000000000000000000..2c07e341a8e60088498349072e92979314dd759d
--- /dev/null
+++ b/projects/lago_v1_3/src/lago.h
@@ -0,0 +1,48 @@
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+#include <poll.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+//#include <fstream>
+//#include <iostream>
+//#include <vector>
+
+#define _GNU_SOURCE
+#include <pthread.h>
+
+#include "zynq_io.h"
+#include "gps_rp.h"
+#include "bmp180.h"
+#include "globaldefs.h"
+
+typedef struct ldata 
+{
+        int trigg_1;   // trigger level ch1
+        int trigg_2;   // trigger level ch2
+        int strigg_1;  // sub-trigger level ch1
+        int strigg_2;  // sub-trigger level ch2
+        int nsamples;  // N of samples
+        int time;
+        double latitude;
+        char lat;
+        double longitude;
+        char lon;
+        uint8_t quality;
+        uint8_t satellites;
+        double altitude;
+} ldata_t;
+
+int  main(int argc, char *argv[]);
+void signal_handler(int sig);
+int  wait_for_interrupt(int fd_int, void *dev_ptr);
+void *thread_isr_not_gps(void *p);  
+void *thread_isr(void *p);  
+void show_usage(char *progname);
+void StrcpyS(char *szDst, size_t cchDst, const char *szSrc); 
+int  parse_param(int argc, char *argv[]);  
+int  new_file(void);
+int  read_buffer(int position, void *bmp);
+
+#endif
diff --git a/projects/lago_v1_3/src/nmea_rp.c b/projects/lago_v1_3/src/nmea_rp.c
new file mode 100644
index 0000000000000000000000000000000000000000..d8c5446bf9e17c46295dd96ffd0696733b218e23
--- /dev/null
+++ b/projects/lago_v1_3/src/nmea_rp.c
@@ -0,0 +1,148 @@
+#include "nmea_rp.h"
+
+static uint8_t rp_NmeaValidChecksum(const char *message) 
+{
+    uint8_t checksum= (uint8_t)strtol(strchr(message, '*')+1, NULL, 16);
+
+    char p;
+    uint8_t sum = 0;
+    ++message;
+    while ((p = *message++) != '*') {
+        sum ^= p;
+    }
+
+    if (sum != checksum) {
+        return NMEA_CHECKSUM_ERR;
+    }
+
+    return _EMPTY;
+}
+
+void rp_NmeaParseGpgga(char *nmea, gpgga_t *loc)
+{
+    char *ptr = nmea;
+    
+    ptr = strchr(ptr, ',')+1; //skip time
+    loc->times = atof(ptr); 
+
+    ptr = strchr(ptr, ',')+1;
+    loc->latitude = atof(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    switch (ptr[0]) {
+        case 'N':
+            loc->lat = 'N';
+            break;
+        case 'S':
+            loc->lat = 'S';
+            break;
+        case ',':
+            loc->lat = '\0';
+            break;
+    }
+
+    ptr = strchr(ptr, ',')+1;
+    loc->longitude = atof(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    switch (ptr[0]) {
+        case 'W':
+            loc->lon = 'W';
+            break;
+        case 'E':
+            loc->lon = 'E';
+            break;
+        case ',':
+            loc->lon = '\0';
+            break;
+    }
+
+    ptr = strchr(ptr, ',')+1;
+    loc->quality = (uint8_t)atoi(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    loc->satellites = (uint8_t)atoi(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+
+    ptr = strchr(ptr, ',')+1;
+    loc->altitude = atof(ptr);
+}
+
+void rp_NmeaParseGprmc(char *nmea, gprmc_t *loc)
+{
+    char *ptr = nmea;
+
+    ptr = strchr(ptr, ',')+1; //skip time
+    loc->times = atof(ptr); 
+
+    ptr = strchr(ptr, ',')+1; //skip status
+
+    ptr = strchr(ptr, ',')+1;
+    loc->latitude = atof(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    switch (ptr[0]) {
+        case 'N':
+            loc->lat = 'N';
+            break;
+        case 'S':
+            loc->lat = 'S';
+            break;
+        case ',':
+            loc->lat = '\0';
+            break;
+    }
+
+    ptr = strchr(ptr, ',')+1;
+    loc->longitude = atof(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    switch (ptr[0]) {
+        case 'W':
+            loc->lon = 'W';
+            break;
+        case 'E':
+            loc->lon = 'E';
+            break;
+        case ',':
+            loc->lon = '\0';
+            break;
+    }
+
+    ptr = strchr(ptr, ',')+1;
+    loc->speed = atof(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    loc->course = atof(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    loc->date = atof(ptr);
+}
+
+/**
+ * Get the message type (GPGGA, GPRMC, etc..)
+ *
+ * This function filters out also wrong packages (invalid checksum)
+ *
+ * @param message The NMEA message
+ * @return The type of message if it is valid
+ */
+uint8_t rp_NmeaGetMessageType(const char *message)
+{
+    uint8_t checksum = 0;
+    if ((checksum = rp_NmeaValidChecksum(message)) != _EMPTY) {
+        return checksum;
+    }
+
+    if (strstr(message, NMEA_GPGGA_STR) != NULL) {
+        return NMEA_GPGGA;
+    }
+
+    if (strstr(message, NMEA_GPRMC_STR) != NULL) {
+        return NMEA_GPRMC;
+    }
+
+    return NMEA_UNKNOWN;
+}
+
diff --git a/projects/lago_v1_3/src/nmea_rp.h b/projects/lago_v1_3/src/nmea_rp.h
new file mode 100644
index 0000000000000000000000000000000000000000..819c5e132f3d0502a3a048d199979a380f71542d
--- /dev/null
+++ b/projects/lago_v1_3/src/nmea_rp.h
@@ -0,0 +1,48 @@
+#ifndef _NMEA_RP_H_
+#define _NMEA_RP_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+#include <math.h>
+
+#define _EMPTY 0x00
+#define NMEA_GPRMC 0x01
+#define NMEA_GPRMC_STR "$GPRMC"
+#define NMEA_GPGGA 0x02
+#define NMEA_GPGGA_STR "$GPGGA"
+#define NMEA_UNKNOWN 0x00
+#define _COMPLETED 0x03
+
+#define NMEA_CHECKSUM_ERR 0x80
+#define NMEA_MESSAGE_ERR 0xC0
+
+typedef struct gpgga {
+    double times;
+    double latitude;
+    char lat;
+    double longitude;
+    char lon;
+    uint8_t quality;
+    uint8_t satellites;
+    double altitude;
+} gpgga_t;
+
+typedef struct gprmc {
+    double times;
+    double latitude;
+    char lat;
+    double longitude;
+    char lon;
+    double speed;
+    double course;
+    double date;
+} gprmc_t;
+
+uint8_t rp_NmeaGetMessageType(const char *);
+void rp_NmeaParseGpgga(char *, gpgga_t *);
+void rp_NmeaParseGprmc(char *, gprmc_t *);
+
+#endif
+
diff --git a/projects/lago_v1_3/src/uart_rp.c b/projects/lago_v1_3/src/uart_rp.c
new file mode 100644
index 0000000000000000000000000000000000000000..8c8391c588c174fca38c5a81f6af27617c8b6c50
--- /dev/null
+++ b/projects/lago_v1_3/src/uart_rp.c
@@ -0,0 +1,79 @@
+#include "uart_rp.h"
+
+/* File descriptor definition */
+int uart_fd = -1;
+
+int rp_UartInit(void)
+{
+	uart_fd = open(PORTNAME, O_RDWR | O_NOCTTY | O_NDELAY);
+
+  if(uart_fd == -1){
+    fprintf(stderr, "Failed to open uart.\n");
+    return -1;
+  }
+	return 0;
+}
+
+void rp_UartConfig(void)
+{
+    struct termios options;
+    tcgetattr(uart_fd, &options);
+		/*Configure the UART
+			see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html */
+    options.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
+    options.c_iflag = IGNPAR;
+    options.c_oflag = 0;
+    options.c_lflag = 0;
+		/* Setting attributes */
+    tcflush(uart_fd, TCIFLUSH);
+    tcsetattr(uart_fd, TCSANOW, &options);
+}
+
+int rp_UartPrintln(const char *line, int len)
+{
+    if (uart_fd != -1) {
+        char *cpstr = (char *)malloc((len+1) * sizeof(char));
+        strcpy(cpstr, line);
+        cpstr[len-1] = '\r';
+        cpstr[len] = '\n';
+
+        int count = write(uart_fd, cpstr, len+1);
+        if (count < 0) {
+					fprintf(stderr, "UART TX error.\n");
+					return -1;
+        }
+        free(cpstr);
+    }
+	return 0;
+}
+
+/* Read a line from UART */
+int rp_UartReadln(char *buffer, int len)
+{
+	char c;
+	char *b = buffer;
+	int rx_length = -1;
+
+	while(1) {
+		rx_length = read(uart_fd, (void*)(&c), 1);
+		
+		if (rx_length <= 0) {
+			//wait for messages
+			 sleep(1);
+		} else {
+		  	if (c == '\n') {
+		    	*b++ = '\0';
+		      break;
+		    }
+		    *b++ = c;
+		}
+	}
+	return 0;
+}
+
+void rp_UartClose(void)
+{
+	tcflush(uart_fd, TCIFLUSH);
+	close(uart_fd);
+}
+
diff --git a/projects/lago_v1_3/src/uart_rp.h b/projects/lago_v1_3/src/uart_rp.h
new file mode 100644
index 0000000000000000000000000000000000000000..72e0fbcfe7a4f2c3d4fbdf02c0b8fce8e9d270da
--- /dev/null
+++ b/projects/lago_v1_3/src/uart_rp.h
@@ -0,0 +1,23 @@
+#ifndef _UART_RP_H_
+#define _UART_RP_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <inttypes.h>
+#include <string.h>
+
+//Default name for UART port in E2 expansion conector
+#ifndef PORTNAME
+#define PORTNAME "/dev/ttyPS1"
+#endif
+
+int rp_UartInit(void);
+void rp_UartConfig(void);
+int rp_UartPrintln(const char *, int);
+int rp_UartReadln(char *, int);
+void rp_UartClose(void);
+
+#endif
diff --git a/projects/lago_v1_3/src/zynq_io.c b/projects/lago_v1_3/src/zynq_io.c
new file mode 100644
index 0000000000000000000000000000000000000000..772c6b431af5c19059e8543d872724795d007448
--- /dev/null
+++ b/projects/lago_v1_3/src/zynq_io.c
@@ -0,0 +1,519 @@
+#include "zynq_io.h"
+
+int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd, hst0_fd, hst1_fd, cma_fd;
+void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr, *hst0_ptr, *hst1_ptr;
+volatile int16_t *cma_ptr;
+uint32_t dev_size;
+
+void dev_write(void *dev_base, uint32_t offset, int32_t value)
+{
+	*((volatile unsigned *)(dev_base + offset)) = value;
+}
+
+uint32_t dev_read(void *dev_base, uint32_t offset)
+{
+	return *((volatile unsigned *)(dev_base + offset));
+}
+
+/*int dev_init(int n_dev)
+	{
+	char *uiod; = "/dev/uio1";
+
+	printf("Initializing device...\n");
+
+// open the UIO device file to allow access to the device in user space
+cfg_fd = open(uiod, O_RDWR);
+if (cfg_fd < 1) {
+printf("cfg_init: Invalid UIO device file:%s.\n", uiod);
+return -1;
+}
+
+dev_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size");
+
+// mmap the cfgC device into user space
+cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, 0);
+if (cfg_ptr == MAP_FAILED) {
+printf("cfg_init: mmap call failure.\n");
+return -1;
+}
+
+return 0;
+}*/
+
+int32_t rd_reg_value(int n_dev, uint32_t reg_off, uint8_t debug)
+{
+	int32_t reg_val;
+	switch(n_dev)
+	{
+		case 0:
+			reg_val = dev_read(intc_ptr, reg_off);
+			break;
+		case 1:
+			reg_val = dev_read(cfg_ptr, reg_off);
+			break;
+		case 2:
+			reg_val = dev_read(sts_ptr, reg_off);
+			break;
+		case 3:
+			reg_val = dev_read(xadc_ptr, reg_off);
+			break;
+		default:
+			printf("Invalid option: %d\n", n_dev);
+			return -1;
+	}
+	if(debug)
+		printf("Complete. Received data 0x%08x\n", reg_val);
+	//printf("Complete. Received data %d\n", reg_val);
+
+	return reg_val;
+}
+
+int32_t wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val, uint8_t debug)
+{
+	switch(n_dev)
+	{
+		case 0:
+			dev_write(intc_ptr, reg_off, reg_val);
+			break;
+		case 1:
+			dev_write(cfg_ptr, reg_off, reg_val);
+			break;
+		case 2:
+			dev_write(sts_ptr, reg_off, reg_val);
+			break;
+		case 3:
+			dev_write(xadc_ptr, reg_off, reg_val);
+			break;
+		default:
+			printf("Invalid option: %d\n", n_dev);
+			return -1;
+	}
+	if(debug)
+		printf("Complete. Data written: 0x%08x\n", reg_val);
+	//printf("Complete. Data written: %d\n", reg_val);
+
+	return 0;
+}
+
+int32_t rd_cfg_status(void)
+{
+	//float a = 0.0382061, b = 4.11435;  // For gain = 1.45
+	float a = 0.0882006, b = 7.73516;  // For gain = 3.2
+
+	printf("#Trigger Level Ch1 = %d\n", dev_read(cfg_ptr, CFG_TRLVL_1_OFFSET));
+	printf("#Trigger Level Ch2 = %d\n", dev_read(cfg_ptr, CFG_TRLVL_2_OFFSET));
+	//printf("#Subtrigger Ch1    = %d\n", dev_read(cfg_ptr, CFG_STRLVL_1_OFFSET));
+	//printf("#Subtrigger Ch2    = %d\n", dev_read(cfg_ptr, CFG_STRLVL_2_OFFSET));
+	printf("#High Voltage 1    = %.1f mV\n", a*dev_read(cfg_ptr, CFG_HV1_OFFSET)+b);
+	printf("#High Voltage 2    = %.1f mV\n", a*dev_read(cfg_ptr, CFG_HV2_OFFSET)+b);
+	printf("#Trigger Scaler 1  = %d\n", dev_read(cfg_ptr, CFG_TR_SCAL_A_OFFSET));
+	printf("#Trigger Scaler 2  = %d\n", dev_read(cfg_ptr, CFG_TR_SCAL_B_OFFSET));
+	if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 1) { // No GPS is present
+		printf("#No GPS device is present or enabled\n");
+	}else{
+		printf("#Using GPS data\n");
+	}
+	if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>5) & 0x1) == 0) //Slave
+	{
+		printf("#Working mode is SLAVE\n");
+	}else{
+		printf("#Working mode is MASTER\n");
+	}
+	printf("\n");
+	printf("Status from registers complete!\n");
+	return 0;
+}
+
+static uint32_t get_memory_size(char *sysfs_path_file)
+{
+	FILE *size_fp;
+	uint32_t size;
+
+	// open the file that describes the memory range size that is based on
+	// the reg property of the node in the device tree
+	size_fp = fopen(sysfs_path_file, "r");
+
+	if (!size_fp) {
+		printf("unable to open the uio size file\n");
+		exit(-1);
+	}
+
+	// get the size which is an ASCII string such as 0xXXXXXXXX and then be
+	// stop using the file
+	if(fscanf(size_fp, "0x%08X", &size) == EOF){
+		printf("unable to get the size of the uio size file\n");
+		exit(-1);
+	}
+	fclose(size_fp);
+
+	return size;
+}
+
+int intc_init(void)
+{
+	char *uiod = "/dev/uio0";
+
+	//printf("Initializing INTC device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	intc_fd = open(uiod, O_RDWR);
+	if (intc_fd < 1) {
+		printf("intc_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio0/maps/map0/size");
+
+	// mmap the INTC device into user space
+	intc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, intc_fd, 0);
+	if (intc_ptr == MAP_FAILED) {
+		printf("intc_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int cfg_init(void)
+{
+	char *uiod = "/dev/uio1";
+
+	//printf("Initializing CFG device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	cfg_fd = open(uiod, O_RDWR);
+	if (cfg_fd < 1) {
+		printf("cfg_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size");
+
+	// mmap the cfgC device into user space
+	cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, 0);
+	if (cfg_ptr == MAP_FAILED) {
+		printf("cfg_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int sts_init(void)
+{
+	char *uiod = "/dev/uio4";
+
+	//printf("Initializing STS device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	sts_fd = open(uiod, O_RDWR);
+	if (sts_fd < 1) {
+		printf("sts_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio4/maps/map0/size");
+
+	// mmap the STS device into user space
+	sts_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, sts_fd, 0);
+	if (sts_ptr == MAP_FAILED) {
+		printf("sts_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int xadc_init(void)
+{
+	char *uiod = "/dev/uio5";
+
+	//printf("Initializing XADC device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	xadc_fd = open(uiod, O_RDWR);
+	if (xadc_fd < 1) {
+		printf("xadc_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio5/maps/map0/size"); 
+
+	// mmap the XADC device into user space
+	xadc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, xadc_fd, 0);
+	if (xadc_ptr == MAP_FAILED) {
+		printf("xadc_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int mem_init(void)
+{
+	char *mem_name = "/dev/mem";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	mem_fd = open(mem_name, O_RDWR);
+	if (mem_fd < 1) {
+		printf("mem_init: Invalid device file:%s.\n", mem_name);
+		return -1;
+	}
+
+	dev_size = 2048*sysconf(_SC_PAGESIZE);
+
+	// mmap the mem device into user space 
+	mem_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0x1E000000);
+	if (mem_ptr == MAP_FAILED) {
+		printf("mem_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int hst0_init(void)
+{
+	char *mem_name = "/dev/mem";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	hst0_fd = open(mem_name, O_RDWR);
+	if (hst0_fd < 1) {
+		printf("hst0_init: Invalid device file:%s.\n", mem_name);
+		return -1;
+	}
+
+	// mmap the mem device into user space 
+	hst0_ptr = mmap(NULL, 16*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, hst0_fd, HST0_BASEADDR);
+	if (hst0_ptr == MAP_FAILED) {
+		printf("mem_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int hst1_init(void)
+{
+	char *mem_name = "/dev/mem";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	hst1_fd = open(mem_name, O_RDWR);
+	if (hst1_fd < 1) {
+		printf("hst1_init: Invalid device file:%s.\n", mem_name);
+		return -1;
+	}
+
+	// mmap the mem device into user space 
+	hst1_ptr = mmap(NULL, 16*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, hst1_fd, HST1_BASEADDR);
+	if (hst1_ptr == MAP_FAILED) {
+		printf("mem_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int cma_init(void)
+{
+	char *cma_name = "/dev/cma";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	cma_fd = open(cma_name, O_RDWR);
+	if (cma_fd < 1) {
+		printf("cma_init: Invalid device file:%s.\n", cma_name);
+		return -1;
+	}
+
+	dev_size = 1024*sysconf(_SC_PAGESIZE);
+
+	if(ioctl(cma_fd, CMA_ALLOC, &dev_size) < 0) {
+		perror("ioctl");
+		return EXIT_FAILURE;
+	}
+	// mmap the mem device into user space 
+	cma_ptr = mmap(NULL, 1024*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, cma_fd, 0);
+	if (cma_ptr == MAP_FAILED) {
+		printf("cma_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+float get_voltage(uint32_t offset)
+{
+	int16_t value;
+	value = (int16_t) dev_read(xadc_ptr, offset);
+	//  printf("The Voltage is: %lf V\n", (value>>4)*XADC_CONV_VAL);
+	return ((value>>4)*XADC_CONV_VAL);
+}       
+
+/*void set_voltage(uint32_t offset, int32_t value)
+	{       
+//fit after calibration. See file data_calib.txt in /ramp_test directory 
+// y = a*x + b
+//a               = 0.0382061     
+//b               = 4.11435   
+uint32_t dac_val;
+float a = 0.0382061, b = 4.11435; 
+
+dac_val = (uint32_t)(value - b)/a;
+
+dev_write(cfg_ptr, offset, dac_val);
+printf("The Voltage is: %d mV\n", value);
+printf("The DAC value is: %d DACs\n", dac_val);
+}
+*/
+
+void set_voltage(uint32_t offset, int32_t value)
+{       
+	//fit after calibration. See file data_calib2.txt in /ramp_test directory 
+	// y = a*x + b
+	//a               = 0.0882006     
+	//b               = 7.73516   
+	uint32_t dac_val;
+	float a = 0.0882006, b = 7.73516; 
+
+	dac_val = (uint32_t)(value - b)/a;
+
+	dev_write(cfg_ptr, offset, dac_val);
+	printf("The Voltage is: %d mV\n", value);
+	printf("The DAC value is: %d DACs\n", dac_val);
+}
+
+float get_temp_AD592(uint32_t offset)
+{
+	float value;
+	value = get_voltage(offset);
+	return ((value*1000)-273.15);
+}       
+
+//System initialization
+int init_system(void)
+{
+	uint32_t reg_val;
+
+	//FIXME: replace hardcoded values for defines
+	// set trigger_lvl_1
+	dev_write(cfg_ptr,CFG_TRLVL_1_OFFSET,8190);
+
+	// set trigger_lvl_2
+	dev_write(cfg_ptr,CFG_TRLVL_2_OFFSET,8190);
+
+	// set subtrigger_lvl_1
+	dev_write(cfg_ptr,CFG_STRLVL_1_OFFSET,8190);
+
+	// set subtrigger_lvl_2
+	dev_write(cfg_ptr,CFG_STRLVL_2_OFFSET,8190);
+
+	// set hv1 and hv2 to zero
+	dev_write(cfg_ptr,CFG_HV1_OFFSET,0);
+	dev_write(cfg_ptr,CFG_HV2_OFFSET,0);
+
+	// reset ramp generators
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~8);
+
+	// reset pps_gen, fifo and trigger modules
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~1);
+
+	/* reset data converter and writer */
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~4);
+
+	// enter reset mode for tlast_gen
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~2);
+
+	// set number of samples
+	dev_write(cfg_ptr,CFG_NSAMPLES_OFFSET, 1024 * 1024);
+
+	// set default value for trigger scalers a and b
+	dev_write(cfg_ptr,CFG_TR_SCAL_A_OFFSET, 1);
+	dev_write(cfg_ptr,CFG_TR_SCAL_B_OFFSET, 1);
+
+	// enter normal mode for tlast_gen
+	/*        reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 2);
+	//printf("written reg_val tlast : 0x%08x\n",reg_val | 2);
+	// enter normal mode for pps_gen, fifo and trigger modules
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 1);
+	//printf("written reg_val pps_gen, fifo : 0x%08x\n",reg_val | 1);
+	*/
+	// enable false GPS
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | FGPS_EN_MASK);
+	//printf("written reg_val : 0x%08x\n",reg_val | 16);
+	// disable
+	//dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~16);
+	//dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~FGPS_EN_MASK);
+	//printf("written reg_val : 0x%08x\n",reg_val & ~16);
+
+	/*        // enter normal mode for data converter and writer
+						reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+						dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 4);
+	//printf("written reg_val : 0x%08hx\n",reg_val | 4);
+	*/
+	// enter normal mode for ramp generators
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 8);
+	// enter in MASTER mode (default)
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 0x20);
+
+	return 0;
+}
+
+int enable_interrupt(void)
+{
+	// steps to accept interrupts -> as pg. 26 of pg099-axi-intc.pdf
+	//1) Each bit in the IER corresponding to an interrupt must be set to 1.
+	dev_write(intc_ptr,XIL_AXI_INTC_IER_OFFSET, 1);
+	//2) There are two bits in the MER. The ME bit must be set to enable the
+	//interrupt request outputs.
+	dev_write(intc_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK | XIL_AXI_INTC_MER_HIE_MASK);
+	//dev_write(dev_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK);
+
+	//The next block of code is to test interrupts by software
+	//3) Software testing can now proceed by writing a 1 to any bit position
+	//in the ISR that corresponds to an existing interrupt input.
+	/*        dev_write(intc_ptr,XIL_AXI_INTC_IPR_OFFSET, 1);
+
+						for(a=0; a<10; a++)
+						{
+						wait_for_interrupt(fd, dev_ptr);
+						dev_write(dev_ptr,XIL_AXI_INTC_ISR_OFFSET, 1); //regenerate interrupt
+						}
+						*/
+	return 0;
+
+}
+
+int disable_interrupt(void)
+{
+	uint32_t value;
+	//Disable interrupt INTC0
+	dev_write(intc_ptr,XIL_AXI_INTC_IER_OFFSET, 0);
+	//disable IRQ
+	value = dev_read(intc_ptr, XIL_AXI_INTC_MER_OFFSET);
+	dev_write(intc_ptr,XIL_AXI_INTC_MER_OFFSET, value | ~1);
+	//Acknowledge any previous interrupt
+	dev_write(intc_ptr, XIL_AXI_INTC_IAR_OFFSET, 1);
+
+	return 0;
+}
+
diff --git a/projects/lago_v1_3/src/zynq_io.h b/projects/lago_v1_3/src/zynq_io.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba466da87eadb67d983e57d2e42340f23a0eb3dd
--- /dev/null
+++ b/projects/lago_v1_3/src/zynq_io.h
@@ -0,0 +1,163 @@
+#ifndef _ZYNQ_IO_H_
+#define _ZYNQ_IO_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#define CMA_ALLOC _IOWR('Z', 0, uint32_t)
+#define INTC_BASEADDR 0x40000000
+#define INTC_HIGHADDR 0x40000FFF
+
+#define CFG_BASEADDR  0x40001000
+#define CFG_HIGHADDR  0x40001FFF
+
+#define STS_BASEADDR  0x40002000
+#define STS_HIGHADDR  0x40002FFF
+
+#define XADC_BASEADDR 0x40003000
+#define XADC_HIGHADDR 0x40003FFF
+
+#define HST0_BASEADDR 0x40010000
+#define HST0_HIGHADDR 0x4001FFFF
+
+#define HST1_BASEADDR 0x40020000
+#define HST1_HIGHADDR 0x4002FFFF
+
+#define XIL_AXI_INTC_ISR_OFFSET    0x0
+#define XIL_AXI_INTC_IPR_OFFSET    0x4
+#define XIL_AXI_INTC_IER_OFFSET    0x8
+#define XIL_AXI_INTC_IAR_OFFSET    0xC
+#define XIL_AXI_INTC_SIE_OFFSET    0x10
+#define XIL_AXI_INTC_CIE_OFFSET    0x14
+#define XIL_AXI_INTC_IVR_OFFSET    0x18
+#define XIL_AXI_INTC_MER_OFFSET    0x1C
+#define XIL_AXI_INTC_IMR_OFFSET    0x20
+#define XIL_AXI_INTC_ILR_OFFSET    0x24
+#define XIL_AXI_INTC_IVAR_OFFSET   0x100
+
+#define XIL_AXI_INTC_MER_ME_MASK 0x00000001
+#define XIL_AXI_INTC_MER_HIE_MASK 0x00000002
+
+//CFG
+#define CFG_RESET_GRAL_OFFSET    0x0
+#define CFG_NSAMPLES_OFFSET      0x4
+#define CFG_TRLVL_1_OFFSET       0x8
+#define CFG_TRLVL_2_OFFSET       0xC
+#define CFG_STRLVL_1_OFFSET      0x10
+#define CFG_STRLVL_2_OFFSET      0x14
+#define CFG_TEMPERATURE_OFFSET   0x18
+#define CFG_PRESSURE_OFFSET      0x1C
+#define CFG_TIME_OFFSET          0x20
+#define CFG_DATE_OFFSET          0x24
+#define CFG_LATITUDE_OFFSET      0x28
+#define CFG_LONGITUDE_OFFSET     0x2C
+#define CFG_ALTITUDE_OFFSET      0x30
+#define CFG_SATELLITE_OFFSET     0x34
+#define CFG_TR_SCAL_A_OFFSET     0x38
+#define CFG_TR_SCAL_B_OFFSET     0x3C
+#define CFG_HV1_OFFSET           0x4C //DAC_PWM3
+#define CFG_HV2_OFFSET           0x48 //DAC_PWM2
+#define CFG_HV3_OFFSET           0x40 //DAC_PWM0
+#define CFG_HV4_OFFSET           0x44 //DAC_PWM1
+#define CFG_HST0_OFFSET          0x50
+#define CFG_HST1_OFFSET          0x54
+#define CFG_WR_ADDR_OFFSET       0x58 //writer address
+
+//CFG Slow DAC
+#define CFG_DAC_PWM0_OFFSET 0x40
+#define CFG_DAC_PWM1_OFFSET 0x44
+#define CFG_DAC_PWM2_OFFSET 0x48
+#define CFG_DAC_PWM3_OFFSET 0x4C
+
+#define ENBL_ALL_MASK         0xFFFFFFFF
+#define RST_ALL_MASK          0x00000000
+#define RST_PPS_TRG_FIFO_MASK 0x00000001
+#define RST_TLAST_GEN_MASK    0x00000002
+#define RST_WRITER_MASK       0x00000004
+#define RST_AO_MASK           0x00000008
+#define FGPS_EN_MASK          0x00000010
+
+//STS
+#define STS_STATUS_OFFSET     0x0
+
+//XADC
+//See page 17 of PG091
+#define XADC_SRR_OFFSET          0x00   //Software reset register
+#define XADC_SR_OFFSET           0x04   //Status Register
+#define XADC_AOSR_OFFSET         0x08   //Alarm Out Status Register
+#define XADC_CONVSTR_OFFSET      0x0C   //CONVST Register
+#define XADC_SYSMONRR_OFFSET     0x10   //XADC Reset Register
+#define XADC_GIER_OFFSET         0x5C   //Global Interrupt Enable Register
+#define XADC_IPISR_OFFSET        0x60   //IP Interrupt Status Register
+#define XADC_IPIER_OFFSET        0x68   //IP Interrupt Enable Register
+#define XADC_TEMPERATURE_OFFSET  0x200  //Temperature
+#define XADC_VCCINT_OFFSET       0x204  //VCCINT
+#define XADC_VCCAUX_OFFSET       0x208  //VCCAUX
+#define XADC_VPVN_OFFSET         0x20C  //VP/VN
+#define XADC_VREFP_OFFSET        0x210  //VREFP
+#define XADC_VREFN_OFFSET        0x214  //VREFN
+#define XADC_VBRAM_OFFSET        0x218  //VBRAM
+#define XADC_UNDEF_OFFSET        0x21C  //Undefined
+#define XADC_SPLYOFF_OFFSET      0x220  //Supply Offset
+#define XADC_ADCOFF_OFFSET       0x224  //ADC Offset
+#define XADC_GAIN_ERR_OFFSET     0x228  //Gain Error
+#define XADC_ZDC_SPLY_OFFSET     0x234  //Zynq-7000 Device Core Supply
+#define XADC_ZDC_AUX_SPLY_OFFSET 0x238  //Zynq-7000 Device Core Aux Supply
+#define XADC_ZDC_MEM_SPLY_OFFSET 0x23C  //Zynq-7000 Device Core Memory Supply
+#define XADC_VAUX_PN_0_OFFSET    0x240  //VAUXP[0]/VAUXN[0]
+#define XADC_VAUX_PN_1_OFFSET    0x244  //VAUXP[1]/VAUXN[1]
+#define XADC_VAUX_PN_2_OFFSET    0x248  //VAUXP[2]/VAUXN[2]
+#define XADC_VAUX_PN_3_OFFSET    0x24C  //VAUXP[3]/VAUXN[3]
+#define XADC_VAUX_PN_4_OFFSET    0x250  //VAUXP[4]/VAUXN[4]
+#define XADC_VAUX_PN_5_OFFSET    0x254  //VAUXP[5]/VAUXN[5]
+#define XADC_VAUX_PN_6_OFFSET    0x258  //VAUXP[6]/VAUXN[6]
+#define XADC_VAUX_PN_7_OFFSET    0x25C  //VAUXP[7]/VAUXN[7]
+#define XADC_VAUX_PN_8_OFFSET    0x260  //VAUXP[8]/VAUXN[8]
+#define XADC_VAUX_PN_9_OFFSET    0x264  //VAUXP[9]/VAUXN[9]
+#define XADC_VAUX_PN_10_OFFSET   0x268  //VAUXP[10]/VAUXN[10]
+#define XADC_VAUX_PN_11_OFFSET   0x26C  //VAUXP[11]/VAUXN[11]
+#define XADC_VAUX_PN_12_OFFSET   0x270  //VAUXP[12]/VAUXN[12]
+#define XADC_VAUX_PN_13_OFFSET   0x274  //VAUXP[13]/VAUXN[13]
+#define XADC_VAUX_PN_14_OFFSET   0x278  //VAUXP[14]/VAUXN[14]
+#define XADC_VAUX_PN_15_OFFSET   0x27C  //VAUXP[15]/VAUXN[15]
+
+#define XADC_AI0_OFFSET XADC_VAUX_PN_8_OFFSET
+#define XADC_AI1_OFFSET XADC_VAUX_PN_0_OFFSET
+#define XADC_AI2_OFFSET XADC_VAUX_PN_1_OFFSET
+#define XADC_AI3_OFFSET XADC_VAUX_PN_9_OFFSET
+
+#define XADC_CONV_VAL 0.00171191993362 //(A_ip/2^12)*(34.99/4.99)
+#define XADC_RDIV_VAL 1.883236177     //voltage divisor in board (15k+16.983k)/16.983k = 1.88
+#define XADC_BASE_HVDIV 0.00294088    //voltage divisor in HV base board (100k/31.3Meg) = 3.194888179. The value I put here is the measured one.
+
+extern int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd, hst0_fd, hst1_fd, cma_fd;
+extern void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr, *hst0_ptr, *hst1_ptr;
+extern volatile int16_t *cma_ptr;
+extern uint32_t dev_size;
+
+void     dev_write(void *dev_base, uint32_t offset, int32_t value);
+uint32_t dev_read(void *dev_base, uint32_t offset);
+//int    dev_init(int n_dev);
+int32_t  rd_reg_value(int n_dev, uint32_t reg_off, uint8_t degug);
+int32_t  wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val, uint8_t debug);
+int32_t  rd_cfg_status(void);
+int      intc_init(void);
+int      cfg_init(void);
+int      sts_init(void);
+int      xadc_init(void);
+int      mem_init(void);
+int      cma_init(void);
+float    get_voltage(uint32_t offset);
+void     set_voltage(uint32_t offset, int32_t value);
+float    get_temp_AD592(uint32_t offset);
+int      init_system(void);
+int      enable_interrupt(void);
+int      disable_interrupt(void);
+
+#endif
+
diff --git a/projects/led_blinker/app/index.html b/projects/led_blinker/app/index.html
deleted file mode 100644
index 11f7dfe5413654d2d0510fad5afa1ea8374eff22..0000000000000000000000000000000000000000
--- a/projects/led_blinker/app/index.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!doctype html>
-<html>
-<head>
-<meta charset="utf-8">
-<title>LED blinker</title>
-<link rel="stylesheet" href="/css/main.css">
-<link rel="stylesheet" href="/css/pygments.css">
-</head>
-<body>
-<div id="header">
-<div id="logo">
-<a href="/">Back to all apps</a>
-</div>
-<div id="menu">
-<a href="https://github.com/pavel-demin/red-pitaya-notes" target="_blank">Source</a>
-<a href="https://github.com/pavel-demin/red-pitaya-notes/issues" target="_blank">Issues</a>
-</div>
-</div>
-<div id="content">
-<h1>LED blinker</h1>
-<p>The LED blinker application is ready.</p>
-</div>
-</body>
-</html>
diff --git a/projects/led_blinker/app/start.sh b/projects/led_blinker/app/start.sh
deleted file mode 100755
index c2cb31d1eefd065502e603fdbe0b6b3e6c4f59c1..0000000000000000000000000000000000000000
--- a/projects/led_blinker/app/start.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#! /bin/sh
-
-apps_dir=/media/mmcblk0p1/apps
-
-source $apps_dir/stop.sh
-
-cat $apps_dir/led_blinker/led_blinker.bit > /dev/xdevcfg