diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ae4adab126d01b43f9cb6b1e78aa7854918fd806
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,105 @@
+# Pre-requisites about cmake itself
+CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
+
+if(COMMAND cmake_policy)
+  cmake_policy(SET CMP0005 NEW) 
+  cmake_policy(SET CMP0003 NEW)
+   
+endif(COMMAND cmake_policy)
+
+# The project name and the type of project
+PROJECT(asterx1_gps)
+
+SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin)
+SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib)
+SET(CMAKE_INSTALL_PREFIX /usr/local)
+
+IF (NOT CMAKE_BUILD_TYPE)
+ SET(CMAKE_BUILD_TYPE "DEBUG") 
+ENDIF (NOT CMAKE_BUILD_TYPE)
+
+SET(CMAKE_C_FLAGS_DEBUG "-g -Wall -D_REENTRANT")
+SET(CMAKE_C_FLAGS_RELEASE "-O3 -D_REENTRANT")
+
+ADD_SUBDIRECTORY(src)
+
+FIND_PACKAGE(Doxygen)
+
+FIND_PATH(IRI_DOC_DIR doxygen.conf ${CMAKE_SOURCE_DIR}/doc/iri_doc/)
+IF (IRI_DOC_DIR)
+  ADD_CUSTOM_TARGET (doc ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/doc/iri_doc/doxygen.conf)
+ELSE (IRI_DOC_DIR)
+  ADD_CUSTOM_TARGET (doc ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/doc/doxygen.conf)
+ENDIF (IRI_DOC_DIR)
+
+ADD_CUSTOM_TARGET (distclean @echo cleaning cmake files)
+
+IF (UNIX)
+  ADD_CUSTOM_COMMAND(
+    COMMENT "distribution clean"
+    COMMAND make ARGS clean
+    COMMAND rm ARGS -rf ${CMAKE_SOURCE_DIR}/build/CMakeFiles*
+    COMMAND rm ARGS -rf ${CMAKE_SOURCE_DIR}/build/src*
+    COMMAND rm ARGS CMakeCache.txt
+    COMMAND rm ARGS cmake_install.cmake
+    COMMAND rm ARGS install_manifest.txt
+    COMMAND rm ARGS Makefile
+
+    TARGET  distclean
+  )
+ELSE(UNIX)
+  ADD_CUSTOM_COMMAND(
+    COMMENT "distclean only implemented in unix"
+    TARGET  distclean
+  )
+ENDIF(UNIX)
+
+ADD_CUSTOM_TARGET (uninstall @echo uninstall package)
+
+IF (UNIX)
+  ADD_CUSTOM_COMMAND(
+    COMMENT "uninstall package"
+    COMMAND xargs ARGS rm < install_manifest.txt
+
+    TARGET  uninstall
+  )
+ELSE(UNIX)
+  ADD_CUSTOM_COMMAND(
+    COMMENT "uninstall only implemented in unix"
+    TARGET  uninstall
+  )
+ENDIF(UNIX)
+
+ADD_CUSTOM_TARGET (dep @echo install package dependencies)
+
+IF (UNIX)
+  ADD_CUSTOM_COMMAND(
+    COMMENT "make package dependencies"
+    COMMAND ./make_dep.sh ARGS -d ../dependencies
+    TARGET  dep
+  )
+ELSE(UNIX)
+  ADD_CUSTOM_COMMAND(
+    COMMENT "make package dependencies only implemented in unix"
+    TARGET  dep
+  )
+ENDIF(UNIX)
+
+
+IF (UNIX)
+  SET(CPACK_PACKAGE_FILE_NAME "iri-${PROJECT_NAME}-dev-${CPACK_PACKAGE_VERSION}${DISTRIB}${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
+  SET(CPACK_PACKAGE_NAME "iri-${PROJECT_NAME}-dev")
+  SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Part of IRI-laboratory libraries. More information at http://wikiri.upc.es/index.php/Robotics_Lab")
+  SET(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
+  SET(CPACK_GENERATOR "DEB")
+  SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "labrobotica@iri.upc.edu")
+  SET(CPACK_SET_DESTDIR "ON")  # Necessary because of the absolute install paths
+
+  INCLUDE(CPack)
+ELSE(UNIX)
+  ADD_CUSTOM_COMMAND(
+    COMMENT "packaging only implemented in unix"
+    TARGET  uninstall
+  )
+ENDIF(UNIX)
+
diff --git a/Findasterx1.cmake b/Findasterx1.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..1ef5ebc8f6836cc7a7626149ff90a7c2f7dd8dfc
--- /dev/null
+++ b/Findasterx1.cmake
@@ -0,0 +1,22 @@
+#edit the following line to add the librarie's header files
+#FIND_PATH(asterx1_INCLUDE_DIR src/asterx1.h src/asterx1exceptions.h /usr/include/iridrivers /usr/local/include/iridrivers)
+FIND_PATH(asterx1_INCLUDE_DIR asterx1.h asterx1exceptions.h /usr/include/iridrivers /usr/local/include/iridrivers)
+
+FIND_LIBRARY(asterx1_LIBRARY
+    NAMES asterx1
+    PATHS /usr/lib /usr/local/lib /usr/local/lib/iridrivers)
+
+IF (asterx1_INCLUDE_DIR AND asterx1_LIBRARY)
+   SET(asterx1_FOUND TRUE)
+ENDIF (asterx1_INCLUDE_DIR AND asterx1_LIBRARY)
+
+IF (asterx1_FOUND)
+   IF (NOT asterx1_FIND_QUIETLY)
+      MESSAGE(STATUS "Found asterx1: ${asterx1_LIBRARY}")
+   ENDIF (NOT asterx1_FIND_QUIETLY)
+ELSE (asterx1_FOUND)
+   IF (asterx1_FIND_REQUIRED)
+      MESSAGE(FATAL_ERROR "Could not find asterx1")
+   ENDIF (asterx1_FIND_REQUIRED)
+ENDIF (asterx1_FOUND)
+
diff --git a/Findasterx1_gps.cmake b/Findasterx1_gps.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..74f474d6849aed412ba0b903de0b98e1c678942d
--- /dev/null
+++ b/Findasterx1_gps.cmake
@@ -0,0 +1,21 @@
+#edit the following line to add the librarie's header files
+FIND_PATH(asterx1_gps_INCLUDE_DIR asterx1_gps.h asterx1exceptions.h /usr/include/iridrivers /usr/local/include/iridrivers)
+
+FIND_LIBRARY(asterx1_gps_LIBRARY
+    NAMES asterx1_gps
+    PATHS /usr/lib /usr/local/lib /usr/local/lib/iridrivers) 
+
+IF (asterx1_gps_INCLUDE_DIR AND asterx1_gps_LIBRARY)
+   SET(asterx1_gps_FOUND TRUE)
+ENDIF (asterx1_gps_INCLUDE_DIR AND asterx1_gps_LIBRARY)
+
+IF (asterx1_gps_FOUND)
+   IF (NOT asterx1_gps_FIND_QUIETLY)
+      MESSAGE(STATUS "Found asterx1_gps: ${asterx1_gps_LIBRARY}")
+   ENDIF (NOT asterx1_gps_FIND_QUIETLY)
+ELSE (asterx1_gps_FOUND)
+   IF (asterx1_gps_FIND_REQUIRED)
+      MESSAGE(FATAL_ERROR "Could not find asterx1_gps")
+   ENDIF (asterx1_gps_FIND_REQUIRED)
+ENDIF (asterx1_gps_FOUND)
+
diff --git a/ReadMe.txt b/ReadMe.txt
new file mode 100644
index 0000000000000000000000000000000000000000..466329af1e09d0934bd4d88fffb48c7461f491b3
--- /dev/null
+++ b/ReadMe.txt
@@ -0,0 +1,19 @@
+Copyright (C) 2009-2010 Institut de Robòtica i Informàtica Industrial, CSIC-UPC.
+Author mmorta (mmorta@iri.upc.edu)
+All rights reserved.
+
+This file is part of asterx1_gps library
+asterx1_gps library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>
+
+
diff --git a/build/make_dep.sh b/build/make_dep.sh
new file mode 100755
index 0000000000000000000000000000000000000000..827a487c5416a2c114194ac16e026485a6d2a57b
--- /dev/null
+++ b/build/make_dep.sh
@@ -0,0 +1,92 @@
+#! /bin/bash
+
+# check wether the script is called as root or not
+if [ "$(id -u)" != "0" ]; then
+   echo "This script must be run as root" 1>&2
+   exit 
+fi
+
+DEP_FILE=
+
+# parse the arguments
+while getopts “d:” OPTION
+do
+  case $OPTION in
+    d)
+       DEP_FILE=$OPTARG
+       ;;
+    ?)
+       echo invalid argument $OPTION
+       exit
+       ;;
+  esac
+done
+
+# check wether a dependencies file has been provided
+if [ "$DEP_FILE" ]
+then
+  echo "using $DEP_FILE file for dependencies ..."
+else
+  echo "No dependencies file provided, aborting ..."  
+  exit 
+fi
+
+LOCAL_REPO_PATH=/usr/local/src/iri
+
+#check wether the repository directory exists or not
+if [ ! -d $LOCAL_REPO_PATH ]
+then
+  mkdir $LOCAL_REPO_PATH
+fi
+
+while read curline; do
+  COMPILE=0
+  MAKE_DEP=0
+  cd $LOCAL_REPO_PATH
+  echo "checking dependency $curline ..."
+  DEP_NAME=$(basename $curline)
+  if [ -d "$DEP_NAME" ]
+  then
+    echo "The $DEP_NAME library is present ... checking updates."
+    cd $DEP_NAME
+    LOCAL_REV_NUM=$(svn info | sed -n 's/^Revision: \([0-9]\+\)$/\1/p')
+    echo "Local $DEP_NAME library revision: $LOCAL_REV_NUM"
+    REPO_REV_NUM=$(svn info | sed -n 's/^Last Changed Rev: \([0-9]\+\)$/\1/p')
+    echo "Repository $DEP_NAME library revision: $REPO_REV_NUM"
+    if [ $LOCAL_REV_NUM -gt $REPO_REV_NUM ] 
+    then
+      echo "There exist local changes that are not commited to the repository"
+    else
+      if [ $LOCAL_REV_NUM -lt $REPO_REV_NUM ] 
+      then
+        echo "Updating to the latest revision ..."
+        svn update
+        COMPILE=1
+      else
+        echo "Already at the latest revision."
+        MAKE_DEP=1
+      fi
+    fi
+  else
+    echo "The $DEP_NAME library is not present ... downloading."
+    svn checkout $curline
+    cd $DEP_NAME
+    COMPILE=1
+  fi  
+  cd build
+  if [ $MAKE_DEP -eq 1 ] 
+  then
+    make dep
+  fi
+  # build if necessary
+  if [ $COMPILE -eq 1 ] 
+  then
+    cmake ..
+    make dep
+    make
+    make install
+  fi
+  #back to the root repository source path
+  cd ../../
+done < $DEP_FILE
+
diff --git a/dependencies b/dependencies
new file mode 100644
index 0000000000000000000000000000000000000000..0bcfb859069feca8aee821b9e304a427d8b64665
--- /dev/null
+++ b/dependencies
@@ -0,0 +1,2 @@
+https://haydn.upc.es/labrobotica/pub/drivers/iriutils
+https://haydn.upc.es/labrobotica/pub/drivers/comm
diff --git a/doc/doxygen.conf b/doc/doxygen.conf
new file mode 100644
index 0000000000000000000000000000000000000000..347af2ef86bf4786d49b13d48c12146b0d001b01
--- /dev/null
+++ b/doc/doxygen.conf
@@ -0,0 +1,251 @@
+# Doxyfile 1.5.5
+
+@INCLUDE_PATH = ../doc/
+@INCLUDE = doxygen_project_name.conf
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING      = UTF-8
+PROJECT_NUMBER         = 
+OUTPUT_DIRECTORY       = ../doc
+CREATE_SUBDIRS         = NO
+OUTPUT_LANGUAGE        = English
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = NO
+ABBREVIATE_BRIEF       = 
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        = 
+STRIP_FROM_INC_PATH    = 
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+QT_AUTOBRIEF           = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = NO
+INHERIT_DOCS           = YES
+SEPARATE_MEMBER_PAGES  = NO
+TAB_SIZE               = 8
+ALIASES                = 
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+OPTIMIZE_FOR_FORTRAN   = NO
+OPTIMIZE_OUTPUT_VHDL   = NO
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+SIP_SUPPORT            = NO
+DISTRIBUTE_GROUP_DOC   = NO
+SUBGROUPING            = YES
+TYPEDEF_HIDES_STRUCT   = NO
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = YES
+EXTRACT_LOCAL_METHODS  = NO
+EXTRACT_ANON_NSPACES   = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = NO
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = NO
+SORT_BRIEF_DOCS        = NO
+SORT_GROUP_NAMES       = NO
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = YES
+SHOW_DIRECTORIES       = YES
+FILE_VERSION_FILTER    = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = YES
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = ../src \
+                         ../doc/main.dox
+INPUT_ENCODING         = UTF-8
+FILE_PATTERNS          = *.c \
+                         *.h \
+                         *.cpp
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = *.tab.c \
+                         *.tab.h \
+                         lex* \
+                         *glr.h \
+                         *llr.h \
+                         *glr.c \
+                         *llr.c \
+                         *general.h
+EXCLUDE_SYMBOLS        = 
+EXAMPLE_PATH           = ../src/examples
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = ../doc/images
+INPUT_FILTER           = 
+FILTER_PATTERNS        = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS              = NO
+VERBATIM_HEADERS       = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+GENERATE_DOCSET        = NO
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+HTML_DYNAMIC_SECTIONS  = NO
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = YES
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = _USE_MPI=1
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+MSCGEN_PATH            = 
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = YES
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = NO
+INCLUDE_GRAPH          = NO
+INCLUDED_BY_GRAPH      = NO
+CALL_GRAPH             = YES
+CALLER_GRAPH           = YES
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = NO
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+DOT_GRAPH_MAX_NODES    = 50
+MAX_DOT_GRAPH_DEPTH    = 2
+DOT_TRANSPARENT        = YES
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
diff --git a/doc/doxygen_project_name.conf b/doc/doxygen_project_name.conf
new file mode 100644
index 0000000000000000000000000000000000000000..e8d97291fd31e3fdfcc4d47aa84628a0374233d5
--- /dev/null
+++ b/doc/doxygen_project_name.conf
@@ -0,0 +1 @@
+PROJECT_NAME = "asterx1_gps"
diff --git a/doc/main.dox b/doc/main.dox
new file mode 100644
index 0000000000000000000000000000000000000000..f88fff805df992f9f50f9cda996cffb7d9196c5d
--- /dev/null
+++ b/doc/main.dox
@@ -0,0 +1,107 @@
+/*! \mainpage asterx1_gps
+
+  \section Introduction 
+
+  \subsection Pre-Requisites
+
+  This package requires of the following libraries and packages
+	 - <A href="http://www.cmake.org">cmake</A>, a cross-platform build system.
+	 - <A href="http://www.doxygen.org">doxygen</a> and 
+	   <A href="http://www.graphviz.org">graphviz</a> to generate the documentation.
+         - stdc++, 
+	 .
+  
+  Under linux all of these utilities are available in ready-to-use packages.
+
+  Under MacOS most of the packages are available via <a href="http://www.finkproject.org/">fink</a>. <br>
+
+  \subsection Compilation
+
+  Just download this package, uncompress it, and execute
+   - cd build
+   - cmake ..
+   .
+  to generate the makefile and then
+   - make
+   .
+  to obtain the shared library (in this case called <em>iriutils.so</em>) and
+  also all the example programs.
+
+  The <em>cmake</em> only need to be executed once (make will automatically call
+  <em>cmake</em> if you modify one of the <em>CMakeList.txt</em> files).
+
+  To generate this documentation type
+       - make doc
+       .
+
+  The files in the <em>build</em> directory are genetated by <em>cmake</em>
+  and <em>make</em> and can be safely removed.
+  After doing so you will need to call cmake manually again.
+
+  \subsection Configuration
+
+  The default build mode is DEBUG. That is, objects and executables 
+  include debug information.
+
+  The RELEASE build mode optimizes for speed. To build in this mode
+  execute
+      - cmake .. -DCMAKE_BUILD_TYPE=RELEASE
+      .
+  The release mode will be kept until next time cmake is executed.
+
+  \subsection Installation
+
+  In order to be able to use the library, it it necessary to copy it into the system.
+  To do that, execute
+
+      - make install
+      .
+
+  as root and the shared libraries will be copied to <em>/usr/local/lib/iriutils</em> directory
+  and the header files will be copied to <em>/usr/local/include/iriutils</em> dierctory. At 
+  this point, the library may be used by any user.
+
+  To remove the library from the system, exceute
+      - make uninstall
+      .
+  as root, and all the associated files will be removed from the system.
+
+  \section Customization
+
+  To build a new application using these library, first it is necessary to locate if the library
+  has been installed or not using the following command
+
+      - FIND_PACKAGE(asterx1 REQUIRED)
+
+  In the case that the package is present, it is necessary to add the header files directory to
+  the include directory path by using
+
+      - INCLUDE_DIRECTORIES(${asterx1_INCLUDE_DIR})
+
+  Finally, it is also nevessary to link with the desired libraries by using the following command
+
+      - TARGET_LINK_LIBRARIES(<executable name> ${asterx1_LIBRARY})
+      .
+
+  \section License
+
+  This package is licensed under a  
+  <a href="http://www.gnu.org/licenses/lgpl.html">
+    LGPL 3.0 License</a>.
+
+  \section Disclaimer
+
+   This is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+
+ */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f76fd514f1a4ebe76a353db1600d50c1c4f301a2
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,31 @@
+# driver source files
+SET(sources asterx1_gps.cpp)
+
+# application header files
+SET(headers asterx1_gps.h)
+
+# locate the the necessary dependencies
+FIND_PACKAGE(iriutils)
+FIND_PACKAGE(comm)
+
+# add the necessary include directories
+INCLUDE_DIRECTORIES(.)
+  INCLUDE_DIRECTORIES(${iriutils_INCLUDE_DIR})
+  INCLUDE_DIRECTORIES(${comm_INCLUDE_DIR})
+
+# create the shared library
+ADD_LIBRARY(asterx1_gps SHARED ${sources})
+
+# link necessary libraries
+TARGET_LINK_LIBRARIES(asterx1_gps ${iriutils_LIBRARY})
+TARGET_LINK_LIBRARIES(asterx1_gps ${comm_LIBRARY})
+INSTALL(TARGETS asterx1_gps
+        RUNTIME DESTINATION bin
+        LIBRARY DESTINATION lib/iridrivers
+        ARCHIVE DESTINATION lib/iridrivers)
+
+INSTALL(FILES ${headers} DESTINATION include/iridrivers)
+
+INSTALL(FILES ../Findasterx1_gps.cmake DESTINATION ${CMAKE_ROOT}/Modules/)
+
+ADD_SUBDIRECTORY(examples)
diff --git a/src/asterx1_gps.cpp b/src/asterx1_gps.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ed57e5879bd1b52ff53370922a12ccec6730887a
--- /dev/null
+++ b/src/asterx1_gps.cpp
@@ -0,0 +1,854 @@
+#include "asterx1_gps.h"
+
+CasteRx1::CasteRx1(const string & hwPortName, const int acqRateIndex)
+{
+	status = 0;
+	config.portName = hwPortName;
+	config.acqPeriod = acqPeriodValues[acqRateIndex];
+}
+
+CasteRx1::~CasteRx1()
+{
+	blockList.clear();
+	if( (status & ACQUISITION_RUNNING) ) stopAcquisition();
+	if( (status & DEVICE_OPEN) ) closeDevice();
+	cout << "CasteRx1::~CasteRx1(). End of CasteRx1 destructor" << endl; //bye bye message
+}
+
+int CasteRx1::openDevice(int xx)
+{
+	cout << xx << endl;
+	int retValue = BASIC_SUCCESS;
+	TRS232_config serialConfig;
+	
+	try{
+		serialPort = new CRS232(config.portName); //creates a new object to manage serial connection
+	}catch(CException &e)
+	{
+		cout << e.what() << endl;
+		cout << "CasteRx1::openDevice(). ERROR. Allocation error when creating new object CRS232" << endl;
+		retValue = PORT_OPEN_ERROR;
+	}	
+	
+	if ( retValue == BASIC_SUCCESS ) //if successfully created , we can open it
+	{
+		try{
+			serialPort->open( (void*)&config.portName ); 
+		}catch(CCommException &e)
+		{
+			cout << e.what() << endl;
+			cout << "CasteRx1::openDevice(). ERROR. Fail to open serial port" << endl;
+			retValue = PORT_OPEN_ERROR;
+		}
+	}
+	
+	if ( retValue == BASIC_SUCCESS ) //if open is successful, we can configure
+	{
+		serialConfig.baud = ASTERX_BAUDRATE;
+		serialConfig.num_bits = 8;
+		serialConfig.parity = none;
+		serialConfig.stop_bits = 1;
+		try{
+			serialPort->config( &serialConfig );
+		}catch(CCommException &e)
+		{
+			cout << e.what() << endl;
+			cout << "CasteRx1::openDevice(). ERROR. Fail to configure serial port" << endl;
+			retValue = PORT_CONFIG_ERROR;
+		}
+	}
+	
+	if (retValue == BASIC_SUCCESS) 
+	{
+		status |= DEVICE_OPEN;
+		cout << "CasteRx1::openDevice(). SUCCESS. Serial port " << config.portName << " opened successfully." << endl;
+		
+	}
+	
+	return retValue;	
+}
+
+int CasteRx1::closeDevice()
+{
+	int retValue = BASIC_SUCCESS;
+
+	if ( (status & DEVICE_OPEN) ) 
+	{
+		try{
+			serialPort->close();
+			//status &= ~DEVICE_OPEN;
+		}catch(CException &e)// catch(CCommException &e)
+		{
+			cout << e.what() << endl;
+			cout << "CasteRx1::openDevice(). ERROR. Fail to close serial port " << config.portName << endl;
+			retValue = PORT_CLOSE_ERROR;
+			//status |= DEVICE_OPEN; //close() has failed , so it is still opened
+		}
+	
+	}
+	if ( retValue == BASIC_SUCCESS ) //if close() is successful, we delete the object
+	{
+		status &= ~DEVICE_OPEN;
+		cout << "CasteRx1::closeDevice(). SUCCESS. Serial port " << config.portName << " closed successfully." << endl;		
+		delete serialPort;
+	}
+	
+	return retValue;
+}
+
+int CasteRx1::startAcquisition()
+{
+	int retValue=0; 
+	sbfBlockManager *blockMng;
+	string cmnd;
+	
+	//enables commands as input at USB1
+	retValue += sendCommand("setDataInOut,USB1,CMD,none\n");
+
+	//stops data transmission if it was running
+	retValue += sendCommand("setSBFOutput,all,USB1,none\n");
+	
+	//enables septentrio binary format (SBF) as output at USB1
+	retValue += sendCommand("setDataInOut,USB1,CMD,+SBF\n");
+	
+	//GPS signal processing options for urban mobile robots
+	retValue += sendCommand("setMultipathMitigation,on\n");//enables processing for multipath removing (pag.26)
+	retValue += sendCommand("setReceiverDynamics,Moderate\n");//Mobile robots moves at moderate speeds
+	retValue += sendCommand("setPVTMode,Rover,StandAlone\n");//rover mode and enables standalone
+	
+	//data configuration. Add blocks of interest to "group 1"
+	retValue += sendCommand("setSBFGroups,Group1,PVTCartesian\n");
+	blockMng = new sbfBlockManager; blockMng->blockId = PVTCartesian_ID; blockMng->received = false;
+	blockList.push_back(*blockMng);
+	
+	retValue += sendCommand("setSBFGroups,Group1,+PosCovCartesian\n");
+	blockMng = new sbfBlockManager; blockMng->blockId = PosCovCartesian_ID; blockMng->received = false;
+	blockList.push_back(*blockMng);
+
+	retValue += sendCommand("setSBFGroups,Group1,+DOP\n");
+	blockMng = new sbfBlockManager; blockMng->blockId = DOP_ID; blockMng->received = false;
+	blockList.push_back(*blockMng);
+	
+	retValue += sendCommand("setSBFGroups,Group1,+PVTGeodetic\n");
+	blockMng = new sbfBlockManager; blockMng->blockId = PVTGeodetic_ID; blockMng->received = false;
+	blockList.push_back(*blockMng);
+	
+	//requests "Group1" data to be output to USB1 at specified rate 
+	cmnd = "setSBFOutput,Stream1,USB1,Group1,";
+	cmnd.append(config.acqPeriod);
+	cmnd.append("\n");
+	retValue += sendCommand(cmnd);
+	//retValue += sendCommand("setSBFOutput,Stream1,USB1,Group1,msec500\n");
+	
+	if ( retValue == BASIC_SUCCESS*11 ) //success on all commands
+	{
+		status |= ACQUISITION_RUNNING;
+		retValue = BASIC_SUCCESS;
+		cout << "CasteRx1::startAcquisition(). SUCCESS on device configuration. The device is now transmitting data ..." << endl;
+	}
+	else //otherwise
+	{
+		status &= ~ACQUISITION_RUNNING;
+		retValue = ASTERX_CONFIG_ERROR;
+		cout << "CasteRx1::startAcquisition(). ERROR on device configuration for data transmission" << endl;
+	}
+
+	return retValue;
+}
+
+int CasteRx1::stopAcquisition()
+{
+	int retValue=0; 
+	
+	if( (status & ACQUISITION_RUNNING) ) 
+	{
+		blockList.clear();
+	
+		retValue += sendCommand("setSBFOutput,Stream1,USB1,none\n");//stops data transmission from device
+		retValue += sendCommand("setDataInOut,USB1,CMD,none\n");//enables commands as input at USB1		
+		if ( retValue == BASIC_SUCCESS*2 )
+		{
+			status &= ~ACQUISITION_RUNNING;
+			retValue = BASIC_SUCCESS;
+			cout << "CasteRx1::stopAcquisition(). SUCCESS on stopping the device data transmission." << endl;
+		}
+		else 
+		{
+			retValue = ASTERX1_STOPPINTG_ERROR;
+			cout << "CasteRx1::stopAcquisition(). ERROR on stopping the device data transmission." << endl;
+		}
+	}
+	else 
+	{
+		cout << "CasteRx1::stopAcquisition(). Nothing to do, the acquisition was already stopped." << endl;
+		retValue = BASIC_SUCCESS;
+	}
+	
+	return retValue;
+}
+
+int CasteRx1::readDataFromDevice()
+{
+	int retValue;
+	unsigned char buffer[MAX_BLOCK_SIZE];
+	unsigned short int crcValue, crcComputed; //crc value from device and crc computed
+	unsigned short int blockId; //data block id from receiver
+	unsigned short int blockLength; //size of the SBF block in bytes
+	timeval tmStmp;
+	list<sbfBlockManager>::iterator iiBlock;	
+	bool allReceived = false;
+	
+	//reset received field of block managers
+	for (iiBlock=blockList.begin();iiBlock!=blockList.end();iiBlock++){ iiBlock->received = false; }
+	
+	//acquisition up to all requested blocks are received
+	while (!allReceived)
+	{
+		//Sets Time Stamp (this is the system time stamp, not the GPS time!)
+		gettimeofday(&tmStmp, NULL); 
+		timeStamp = (double)(tmStmp.tv_sec + tmStmp.tv_usec/1e6);	
+		
+		retValue = synchronizeHeader((const unsigned char *)"$@", DATA_TIMEOUT); 
+		if ( retValue != BASIC_SUCCESS ) //if !BASIC_SUCCESS, status will be either COMMTIMEOUT or SERIALCOMMERROR
+		{
+			status &= ~DATA_BLOCK_OK;
+			cout << "CasteRx1::readDataFromDevice(). ERROR. when synchronizing with header. Expected header = $@" << endl;
+			return ACQUISITION_ERROR; 
+		}		
+
+		//starts reading header
+		retValue = 0;
+		retValue += readNbytes(&buffer[0],2,DATA_TIMEOUT);//reads transmitted crc value
+		crcValue = getUI2(&buffer[0]); //decodes crc value
+		retValue += readNbytes(&buffer[0],2,DATA_TIMEOUT);//reads block id field
+		blockId = (buffer[0] & 0xff)|((buffer[1] & 0x1f)<<8);//decodes blockId (usies only the 13 LS bits)
+		retValue += readNbytes(&buffer[2],2,DATA_TIMEOUT);//reads block length
+		blockLength = getUI2(&buffer[2]);//decodes block length (in bytes)
+
+		//check for some errors
+		if ( retValue != 3*BASIC_SUCCESS )
+		{
+			status &= ~DATA_BLOCK_OK;
+			cout << "CasteRx1::readDataFromDevice(). ERROR. Error reading block header." << endl;
+			return ACQUISITION_ERROR; 
+		}
+		if ( (blockLength%4!=0) || (blockLength < MIN_BLOCK_SIZE) || (blockLength > MAX_BLOCK_SIZE) )
+		{
+			status &= ~DATA_BLOCK_OK;
+			cout << "CasteRx1::readDataFromDevice(). ERROR. SBF block Length not correct: " << blockLength << " bytes" << endl;
+			return ACQUISITION_ERROR; 
+		}
+		
+		//cout << "readDataFromDevice(): "<< __LINE__ << "; blockLength = " << blockLength << endl;
+		
+		//reads the rest of the block and loads it to the buffer
+		retValue = readNbytes(&buffer[4],(blockLength-8),DATA_TIMEOUT);
+		if ( retValue != BASIC_SUCCESS )
+		{
+			status &= ~DATA_BLOCK_OK;
+			cout << "CasteRx1::readDataFromDevice(). ERROR. Error reading block data." << endl;
+			return ACQUISITION_ERROR; 
+		}
+
+		//Computes & checks CRC
+		crcComputed = CRC_compute16CCITT(buffer, blockLength-4);
+		//cout << "Expected value: " << crcValue << "; Computed value: " << crcComputed << endl;
+		if ( crcComputed != crcValue )
+		{
+			status &= ~DATA_BLOCK_OK;
+			cout << "CasteRx1::readDataFromDevice(). ERROR. CRC error. Expected value: " << crcValue << "; Computed value: " << crcComputed << endl;
+			return ACQUISITION_ERROR; 
+		}
+
+		//decodes SBF block
+		switch(blockId)
+		{
+			case PVTCartesian_ID:
+				retValue = decodePVTCartesian(&buffer[4]);
+				markBlockAsReceived(PVTCartesian_ID);
+				break;
+
+			case PVTGeodetic_ID:
+				retValue = decodePVTGeodetic(&buffer[4]);
+				markBlockAsReceived(PVTGeodetic_ID);
+				break;
+				
+			case PosCovCartesian_ID:
+				retValue = decodePosCovCartesian(&buffer[4]);
+				markBlockAsReceived(PosCovCartesian_ID);
+				break;
+
+			case DOP_ID:
+				retValue = decodeDOP(&buffer[4]);
+				markBlockAsReceived(DOP_ID);
+				break;
+
+			default:
+				cout << "CasteRx1::readDataFromDevice(). ERROR. Unknown SBF blockId: " << blockId << endl;
+				retValue = ACQUISITION_ERROR;
+				break;
+		}
+	
+		//check resulting status of the decoding function
+		if ( retValue != BASIC_SUCCESS )
+		{
+			status &= ~DATA_BLOCK_OK;
+			cout << "CasteRx1::readDataFromDevice(). ERROR on decoding SBF block. BlockId = " << blockId << ". Status = " << status << endl;
+			return ACQUISITION_ERROR;
+		}
+		else//sets status and checks recursively if all blocks have been received
+		{		
+			status |= DATA_BLOCK_OK;
+			allReceived = true;
+			for (iiBlock=blockList.begin();iiBlock!=blockList.end();iiBlock++){ allReceived = iiBlock->received & allReceived; }
+		}
+	}
+
+	//check gps availability
+	if ( pvtError == 0 )
+	{ 
+		status |= GPS_AVAILABLE;
+		fromWgsToMap(); //conversion to map coordinates
+		computeTMenu(); //compute rotation matrix form WGS to local tangential ENU frame
+		computeENUcovs(); //compute covariances from WGS  to local tangential ENU frame
+	}
+	else 
+	{
+		status &= ~GPS_AVAILABLE;
+	}
+
+	return BASIC_SUCCESS;
+}
+
+void CasteRx1::printData(ostream & ost)
+{
+	streamsize nn;
+
+	ost << status << " ";
+	nn=ost.precision(12); ost << timeStamp << " "; ost.precision(nn);
+	ost << wnc << " " << tow << " " << numSatellites << " " << PDOP << " ";
+	nn=ost.precision(12); ost << lat << " " << lon << " " << alt << " "; ost.precision(nn);
+	ost << xWgs << " " << yWgs << " " << zWgs << " ";
+	ost << xMap << " " << yMap << " " << zMap << " ";
+	ost << vxWgs << " " << vyWgs << " " << vzWgs << " ";
+	ost << vxMap << " " << vyMap << " " << vzMap << " ";
+	ost << cxxWgs << " " << cyyWgs << " " << czzWgs << " " << cxyWgs << " ";
+	ost << cxxMap << " " << cyyMap << " " << czzMap << " " << cxyMap << " ";
+	ost << endl;
+}
+
+void CasteRx1::setMapOrigin(double mapLat0, double mapLon0, double mapAlt0, double mapAlpha0)
+{
+	lat0 = mapLat0*M_PI/180.0;
+	lon0 = mapLon0*M_PI/180.0;	
+	alt0 = mapAlt0;
+	alpha0 = mapAlpha0*M_PI/180.0;
+	
+	computeTM();
+}
+
+void CasteRx1::setPortName(string pName)
+{
+	if( (status & DEVICE_OPEN) ) //if device is open, port name can't be changed
+	{
+		cout << "CasteRx1::setPortName(): WARNING! Serial port resource can't be changed when port is open. Keeping old settings: " << config.portName << endl;
+	}
+	else
+	{
+		config.portName = pName;
+		cout << "CasteRx1::setPortName(): Serial port name setting has changed. New serial port is " << config.portName << endl;
+	}
+}
+
+void CasteRx1::setAcquisitionRate(int rateIndex)
+{
+	if (status & ACQUISITION_RUNNING)
+	{
+		cout << "CasteRx1::setAcquisitionRate(): WARNING! Rate can't be changed when acquisition is running. Keeping old settings: " << config.acqPeriod << endl;
+	}
+	else
+	{
+		if ( ( rateIndex<ONCHANGE )|| ( rateIndex>SEC10 ) )
+		{
+			cout << "CasteRx1::setAcquisitionRate(): WARNING! Invalid rate index. Keeping old settings: " << config.acqPeriod << endl;
+		}
+		else
+		{
+			config.acqPeriod = acqPeriodValues[rateIndex];
+			cout << "CasteRx1::setAcquisitionRate(): Acquisition rate has changed. New rate is " << config.acqPeriod << endl;
+		}
+	}
+}
+
+void CasteRx1::printTM()
+{
+	streamsize nn;
+	
+	cout << endl << "MAP ORIGIN (GEODETIC) ----------------------------------" << endl;
+	nn=cout.precision(15);
+	cout << "lat0 = " << lat0 << endl << "lon0 = " << lon0 << endl << "alt0 = " << alt0 << endl << "alpha0 = " << alpha0 << endl;
+	cout.precision(nn);
+
+	cout << endl << "MATRIX TRANSFORM FROM ECEF to MAP-----------------------" << endl;
+	cout 	<< TM[0][0] << '\t' << TM[0][1] << '\t' << TM[0][2] << '\t' << TM[0][3] << endl
+	<< TM[1][0] << '\t' << TM[1][1] << '\t' << TM[1][2] << '\t' << TM[1][3] << endl 
+	<< TM[2][0] << '\t' << TM[2][1] << '\t' << TM[2][2] << '\t' << TM[2][3] << endl 
+	<< TM[3][0] << '\t' << '\t' << TM[3][1] << '\t' << '\t' << TM[3][2] << '\t' << '\t' << TM[3][3] << endl;
+	cout << "--------------------------------------------------------" << endl << endl;
+}
+
+unsigned int CasteRx1::getStatus(){ return status; }
+double CasteRx1::getTimeStamp(){ return timeStamp; }
+unsigned short int CasteRx1::getWnc(){ return wnc; }
+unsigned int CasteRx1::getTow(){ return tow; }
+unsigned int CasteRx1::getNumSatellites(){ return numSatellites; }
+float CasteRx1::getPDOP(){ return PDOP; }
+float CasteRx1::getTDOP(){ return TDOP; }
+float CasteRx1::getHDOP(){ return HDOP; }
+float CasteRx1::getVDOP(){ return VDOP; }
+float CasteRx1::getUndulation(){ return undulation; }
+unsigned short int CasteRx1::getPVTerror(){ return pvtError;}
+
+double CasteRx1::getLat(bool units)
+{ 
+	if ( units == inRADS ) return lat; 
+	else return lat*180.0/M_PI;
+}
+
+double CasteRx1::getLon(bool units)
+{
+	if ( units == inRADS ) return lon; 
+	else return lon*180.0/M_PI;
+}
+
+double CasteRx1::getAlt(){ return alt; }
+double CasteRx1::getXWgs(){ return xWgs; }
+double CasteRx1::getYWgs(){ return yWgs; }
+double CasteRx1::getZWgs(){ return zWgs; }
+double CasteRx1::getXMap(){ return xMap; }
+double CasteRx1::getYMap(){ return yMap; }
+double CasteRx1::getZMap(){ return zMap; }
+double CasteRx1::getVxWgs(){ return vxWgs; }
+double CasteRx1::getVyWgs(){ return vyWgs; }
+double CasteRx1::getVzWgs(){ return vzWgs; }
+double CasteRx1::getVxMap(){ return vxMap; }
+double CasteRx1::getVyMap(){ return vyMap; }
+double CasteRx1::getVzMap(){ return vzMap; }
+double CasteRx1::getCxxWgs(){ return cxxWgs; }
+double CasteRx1::getCyyWgs(){ return cyyWgs; }
+double CasteRx1::getCzzWgs(){ return czzWgs; }
+double CasteRx1::getCxyWgs(){ return cxyWgs; }
+double CasteRx1::getCxxMap(){ return cxxMap; }
+double CasteRx1::getCyyMap(){ return cyyMap; }
+double CasteRx1::getCzzMap(){ return czzMap; }
+double CasteRx1::getCxyMap(){ return cxyMap; }
+double CasteRx1::getCxxEnu(){ return cxxEnu; }
+double CasteRx1::getCyyEnu(){ return cyyEnu; }
+double CasteRx1::getCzzEnu(){ return czzEnu; }
+double CasteRx1::getCxyEnu(){ return cxyEnu; }
+double CasteRx1::getCxzEnu(){ return cxzEnu; }
+double CasteRx1::getCyzEnu(){ return cyzEnu; }		
+
+
+/******************************* PROTECTED MEMBERS ************************************************/
+
+int CasteRx1::readNbytes(unsigned char *buffer, unsigned int nn, unsigned int msecTimeOut)
+{
+	CEventServer *eventServer=CEventServer::instance();
+	string rxEvent;
+	list<string> eventList;
+	unsigned int bytesRead = 0;
+	unsigned int queueSize = 0;
+	unsigned int desiredBytes = 0;
+	int retValue = BASIC_SUCCESS;
+	
+	//sets the event list with the reception event from serialPort object
+	rxEvent = serialPort->get_rx_event_id();
+	eventList.push_back(rxEvent);
+	
+	//first check if some byte is already in the queue
+	queueSize = serialPort->get_num_data();
+	if ( queueSize > 0)
+	{
+		desiredBytes = min( queueSize , (nn-bytesRead) );
+		bytesRead += serialPort->read((unsigned char *)(buffer+bytesRead),desiredBytes);
+	}
+
+	//starts the waiting loop if not all bytes are already read
+	while ( (bytesRead<nn) && (retValue == BASIC_SUCCESS) )
+	{
+		try{
+			eventServer->wait_all(eventList, msecTimeOut);//waits for reception event
+		}catch(CEventServerException &e)
+		{
+			cout << e.what() << ". Line: " << __LINE__ << endl;
+			retValue = PORT_READ_TIMEOUT;
+		}
+		if (retValue == BASIC_SUCCESS)
+		{
+			queueSize = serialPort->get_num_data();
+			desiredBytes = min( queueSize , (nn-bytesRead) );
+			bytesRead += serialPort->read((unsigned char *)(buffer+bytesRead),desiredBytes);
+		}
+	}
+	
+	return retValue;
+}
+
+int CasteRx1::synchronizeHeader(const unsigned char *mark, int msecTimeOut, unsigned int markSize)
+{
+	unsigned char cc; 
+	string readMark, targetMark;
+	bool endLoop = false;
+	int retValue = BASIC_SUCCESS;
+	int ii=0;
+
+	//sets targetMark
+	targetMark.append((const char*)mark,markSize);
+	
+	//reads mark from comm device
+	for (ii=0; ii<markSize; ii++)
+	{
+		retValue = readNbytes(&cc,1,msecTimeOut);
+		readMark.push_back((char)cc);
+	}
+
+	//continue reading while mark is not reached or while timeout
+	while ( (readMark.compare(targetMark) != 0) && (retValue == BASIC_SUCCESS) )
+	{
+		for (ii=1; ii<markSize; ii++) readMark.at(ii-1) = readMark.at(ii); //left displacement of all bytes
+		retValue = readNbytes(&cc,1,msecTimeOut); //gets a new byte
+		readMark.at(markSize-1) = (char)cc; //replace the last byte by the new one
+		//cout << endl << "readMark: " << readMark << endl << "targetMark: " << targetMark << endl;
+	}
+
+	return retValue;
+}
+
+int CasteRx1::sendCommand(const string & cmnd)
+{
+	int retValue;
+	int nn;
+	unsigned char replyBuffer[200];
+	string receivedReply, expectedReply;
+	
+	//relax if we concatenate commands. (200 ms were suggested by Septentrio support team in a personal communication). 50ms tested and it seems it is not enough!!!
+	usleep(100000);
+
+	//sends the command string	
+	serialPort->write((unsigned char*)cmnd.c_str(),cmnd.size());
+	
+	//synchronize with the reply header
+	retValue = synchronizeHeader((const unsigned char *)"$R",500);
+	
+	//cout << "CasteRx1. Line: " << __LINE__ << ". Reply Sync achieved" << endl;
+	if ( retValue != BASIC_SUCCESS )
+	{
+		cout << "CasteRx1::sendCommand(). ERROR. Synchronization with repky header $R not achieved after timeout" <<  endl;
+		return retValue; //it will be either COMMTIMEOUT or SERIALCOMMERROR
+	}
+
+	//reads response up to receive expected length bytes (2 + cmnd.size()). Expected response : "$R: <cmnd>", but $R has been already read
+	retValue = readNbytes(&replyBuffer[0],cmnd.size()+2,500);
+	if ( retValue != BASIC_SUCCESS )
+	{
+		cout << "CasteRx1::sendCommand(). ERROR. Expected reply string not received after timeout" <<  endl;
+		return retValue; //it will be either COMMTIMEOUT or SERIALCOMMERROR
+	}
+	
+	//check response
+	if ( replyBuffer[0] == '?' ) 
+	{
+		cout << "CasteRx1::sendCommand(). ERROR. Unknown command: " << cmnd << endl;
+		return ASTERX1_INVALID_COMMAND;
+	}
+	receivedReply.append((const char*)replyBuffer,cmnd.size()+2);
+	receivedReply.append("\n");
+	expectedReply = ": ";
+	expectedReply.append(cmnd);
+	expectedReply.append("\n");
+	if ( receivedReply.compare(0, cmnd.size()+1, expectedReply, 0, cmnd.size()+1) == 0) //expected = received
+	{
+		//cout << "CasteRx1::sendCommand(). Command Successful: " << cmnd << endl;
+		return BASIC_SUCCESS;
+	}
+	else //otherwise
+	{
+		cout << "CasteRx1::sendCommand(). Error. " << endl;
+		cout << "      Sent   command: " << cmnd << endl;
+		cout << "      Device   Reply: " << receivedReply << endl;
+		cout << "      Expected Reply: " << expectedReply << endl;
+		return ASTERX_CONFIG_ERROR;
+	}
+}
+
+unsigned short int CasteRx1::getUI1(unsigned char *buf)
+{
+	//return ( (buf[0] & 0xff) | (0x0 << 8) );
+	return (buf[0] & 0x00ff);
+}
+
+unsigned short int CasteRx1::getUI2(unsigned char *buf)
+{
+	return ( (buf[0] & 0xff) | ((buf[1]&0xff)<<8) );	
+}
+
+unsigned int CasteRx1::getUI4(unsigned char *buf)
+{
+	return ( (buf[0]&0xff) | ((buf[1]&0xff)<<8) | ((buf[2]&0xff)<<16) | ((buf[3]&0xff)<<24) );	
+}
+
+float CasteRx1::getFloat(unsigned char *buf)
+{
+	unsigned int uintL;
+	uniFloat uniF;
+	
+	uintL=(buf[0]&0xff)|((buf[1]&0xff)<<8)|((buf[2]&0xff)<<16)|((buf[3]&0xff)<<24);
+	uniF.i = uintL;
+	
+	return uniF.flt;	
+}
+
+double CasteRx1::getDouble(unsigned char *buf)
+{
+	unsigned int uintL;
+	unsigned long long int uintH;
+	uniDouble uniD;
+	
+	uintL=(buf[0]&0xff)|((buf[1]&0xff)<<8)|((buf[2]&0xff)<<16)|((buf[3]&0xff)<<24);
+	uintH=(buf[4]&0xff)|((buf[5]&0xff)<<8)|((buf[6]&0xff)<<16)|((buf[7]&0xff)<<24);
+	//uniD.i = uintL|((uintH&0xffff)<<32);
+	uniD.i = uintL|uintH<<32;
+	
+	return uniD.dbl;	
+}
+
+int CasteRx1::decodePVTCartesian(unsigned char *sbfMsg)
+{
+	unsigned short int mode;//PVT computation mode (e.g. standAlone, fixed, differential, rtk,...)
+	
+	tow = getUI4(&sbfMsg[0]);
+	wnc = getUI2(&sbfMsg[4]);
+	mode = getUI1(&sbfMsg[6]);
+	pvtError = getUI1(&sbfMsg[7]);
+	if ( pvtError!=0 ) //GPS error to obtain position (this is not an acquisition error)
+	{
+		//cout << "CasteRx1::decodePVTCartesian(): PVT_ERROR: " << pvtError << endl;
+	}
+	else
+	{
+		xWgs = getDouble(&sbfMsg[8]);
+		yWgs = getDouble(&sbfMsg[16]);	
+		zWgs = getDouble(&sbfMsg[24]);
+		undulation = (double) getFloat(&sbfMsg[32]);
+		vxWgs = (double) getFloat(&sbfMsg[36]);
+		vyWgs = (double) getFloat(&sbfMsg[40]);
+		vzWgs = (double) getFloat(&sbfMsg[44]);
+		numSatellites = getUI1(&sbfMsg[66]);
+	}
+
+	//cout << "CasteRx1::decodePVTCartesian()" << endl;
+	return BASIC_SUCCESS;
+}
+
+int CasteRx1::decodePVTGeodetic(unsigned char *sbfMsg)
+{
+	unsigned short int mode;//PVT computation mode (e.g. standAlone, fixed, differential, rtk,...)
+		
+	tow = getUI4(&sbfMsg[0]);
+	wnc = getUI2(&sbfMsg[4]);
+	mode = getUI1(&sbfMsg[6]);
+	pvtError = getUI1(&sbfMsg[7]);
+	if ( pvtError!=0 ) //GPS error to obtain position (this is not an acquisition error)
+	{
+		//cout << "CasteRx1::decodePVTGeodetic(): PVT_ERROR: " << pvtError << endl;
+	}
+	else 
+	{
+		lat = getDouble(&sbfMsg[8]);
+		lon = getDouble(&sbfMsg[16]);
+		alt = getDouble(&sbfMsg[24]);
+	}
+	
+	//cout << "CasteRx1::decodePVTGeodetic()" << endl;	
+	return BASIC_SUCCESS;
+}
+
+int CasteRx1::decodePosCovCartesian(unsigned char *sbfMsg)
+{	
+	unsigned short int mode;//PVT computation mode (e.g. standAlone, fixed, differential, rtk,...)
+
+	tow = getUI4(&sbfMsg[0]);
+	wnc = getUI2(&sbfMsg[4]);
+	mode = getUI1(&sbfMsg[6]);
+	pvtError = getUI1(&sbfMsg[7]);
+	if ( pvtError!=0 ) //GPS error to obtain position (this is not an acquisition error)
+	{
+		//cout << "CasteRx1::decodePosCovCartesian(): PVT_ERROR: " << pvtError << endl;
+	}
+	else 
+	{
+		cxxWgs = (double) getFloat(&sbfMsg[8]);
+		cyyWgs = (double) getFloat(&sbfMsg[12]);
+		czzWgs = (double) getFloat(&sbfMsg[16]);
+		cxyWgs = (double) getFloat(&sbfMsg[24]);
+		cxzWgs = (double) getFloat(&sbfMsg[28]);
+		cyzWgs = (double) getFloat(&sbfMsg[36]);	
+	}
+	
+	//cout << "CasteRx1::decodePosCovCartesian()" << endl;	
+	return BASIC_SUCCESS;
+}
+
+int CasteRx1::decodeDOP(unsigned char *sbfMsg)
+{
+	unsigned char nrsv;//total number of satellites for DOP computation
+
+	tow = getUI4(&sbfMsg[0]);
+	wnc = getUI2(&sbfMsg[4]);
+	nrsv = getUI1(&sbfMsg[6]);
+
+	PDOP = (double)getUI2(&sbfMsg[8])/100.0;
+	TDOP = (double)getUI2(&sbfMsg[10])/100.0;
+	HDOP = (double)getUI2(&sbfMsg[12])/100.0;
+	VDOP = (double)getUI2(&sbfMsg[14])/100.0;		
+
+	//cout << "CasteRx1::decodeDOP()" << endl;
+	return BASIC_SUCCESS;
+}
+
+//unsigned short CasteRx1::CRC_compute16CCITT(const void *buf, size_t buf_length)
+unsigned short CasteRx1::CRC_compute16CCITT(unsigned char *buf, unsigned short int nBytes)
+{
+  unsigned int  ii;
+  unsigned short  crc = 0;
+  //const unsigned char  *buf8 = buf; /* Convert the type to access by byte. */
+
+  /* see for example the BINEX web site */
+  for (ii=0; ii<nBytes; ii++) {
+    crc = (crc << 8) ^ CRC_16CCIT_LookUp[ (crc >> 8) ^ buf[ii] ];
+  }
+
+  return crc;
+}
+
+void CasteRx1::computeTM()
+{
+	double kk; //constant
+	double xx0,yy0,zz0; //wgs-ecef coordinates of the origin
+	double auxTM[4][4];
+	
+	//sets the rotation part of TM, from ECEF to ENU coordinates
+	auxTM[0][0] = -sin(lon0);
+	auxTM[0][1] = cos(lon0);
+	auxTM[0][2] = 0.0;
+	auxTM[1][0] = -sin(lat0)*cos(lon0);
+	auxTM[1][1] = -sin(lat0)*sin(lon0);
+	auxTM[1][2] = cos(lat0);
+	auxTM[2][0] = cos(lat0)*cos(lon0);
+	auxTM[2][1] = cos(lat0)*sin(lon0);
+	auxTM[2][2] = sin(lat0);
+
+	//computes final alignement of x with respect to the campus baseline as a rotation of alpha0 on z axis
+	//Ra=[cos(alpha0)  sin(alpha0) 0;
+	//   -sin(alpha0)  cos(alpha0) 0;
+	//	0           0          1];
+	TM[0][0]=cos(alpha0)*auxTM[0][0] + sin(alpha0)*auxTM[1][0];
+	TM[0][1]=cos(alpha0)*auxTM[0][1] + sin(alpha0)*auxTM[1][1];
+	TM[0][2]=cos(alpha0)*auxTM[0][2] + sin(alpha0)*auxTM[1][2];
+	TM[1][0]=-sin(alpha0)*auxTM[0][0] + cos(alpha0)*auxTM[1][0];
+	TM[1][1]=-sin(alpha0)*auxTM[0][1] + cos(alpha0)*auxTM[1][1];
+	TM[1][2]=-sin(alpha0)*auxTM[0][2] + cos(alpha0)*auxTM[1][2];
+	TM[2][0]=auxTM[2][0]; 
+	TM[2][1]=auxTM[2][1];
+	TM[2][2]=auxTM[2][2];
+
+	//computes the translation part
+	kk = EARTH_RADIUS/sqrt(1-(pow(EARTH_EXCENTRICITY*sin(lat0),2.0)));
+	xx0 = (kk + alt0) * cos(lat0) * cos(lon0);
+	yy0 = (kk + alt0) * cos(lat0) * sin(lon0);
+	zz0 = ((1-EARTH_EXCENTRICITY*EARTH_EXCENTRICITY)* kk + alt0) * sin(lat0);
+	TM[0][3] = - ( TM[0][0]*xx0 + TM[0][1]*yy0 + TM[0][2]*zz0 );
+	TM[1][3] = - ( TM[1][0]*xx0 + TM[1][1]*yy0 + TM[1][2]*zz0 );
+	TM[2][3] = - ( TM[2][0]*xx0 + TM[2][1]*yy0 + TM[2][2]*zz0 );
+	TM[3][0] = 0.0; 
+	TM[3][1] = 0.0; 
+	TM[3][2] = 0.0;
+	TM[3][3] = 1.0;
+}
+
+void CasteRx1::computeTMenu()
+{
+	//uses current position to compute ENU rotation 
+	TMenu[0][0] = -sin(lon);
+	TMenu[0][1] = cos(lon);
+	TMenu[0][2] = 0.0;
+	TMenu[1][0] = -sin(lat)*cos(lon);
+	TMenu[1][1] = -sin(lat)*sin(lon);
+	TMenu[1][2] = cos(lat);
+	TMenu[2][0] = cos(lat)*cos(lon);
+	TMenu[2][1] = cos(lat)*sin(lon);
+	TMenu[2][2] = sin(lat);
+}
+
+void CasteRx1::fromWgsToMap()
+{
+	double auxM[3][3];
+	int ii;
+
+	//compute map coords
+	xMap=TM[0][0]*xWgs+TM[0][1]*yWgs+TM[0][2]*zWgs+TM[0][3];
+	yMap=TM[1][0]*xWgs+TM[1][1]*yWgs+TM[1][2]*zWgs+TM[1][3];
+	zMap=TM[2][0]*xWgs+TM[2][1]*yWgs+TM[2][2]*zWgs+TM[2][3];
+
+	//compute velocities 
+	vxMap=TM[0][0]*vxWgs+TM[0][1]*vyWgs+TM[0][2]*vzWgs;
+	vyMap=TM[1][0]*vxWgs+TM[1][1]*vyWgs+TM[1][2]*vzWgs;
+	vzMap=TM[2][0]*vxWgs+TM[2][1]*vyWgs+TM[2][2]*vzWgs;
+
+	//compute covariance matrix
+	//firts step: auxM=TM*covEcef
+	for(ii=0;ii<3;ii++)
+	{
+		auxM[ii][0]=TM[ii][0]*cxxWgs+TM[ii][1]*cxyWgs+TM[ii][2]*cxzWgs;
+		auxM[ii][1]=TM[ii][0]*cxyWgs+TM[ii][1]*cyyWgs+TM[ii][2]*cyzWgs;
+		auxM[ii][2]=TM[ii][0]*cxzWgs+TM[ii][1]*cyzWgs+TM[ii][2]*czzWgs;
+	}
+	//second step: covMap = auxM*TM^T
+	cxxMap=auxM[0][0]*TM[0][0]+auxM[0][1]*TM[0][1]+auxM[0][2]*TM[0][2];
+	cyyMap=auxM[1][0]*TM[1][0]+auxM[1][1]*TM[1][1]+auxM[1][2]*TM[1][2];
+	czzMap=auxM[2][0]*TM[2][0]+auxM[2][1]*TM[2][1]+auxM[2][2]*TM[2][2];
+	cxyMap=auxM[0][0]*TM[1][0]+auxM[0][1]*TM[1][1]+auxM[0][2]*TM[1][2];
+}
+
+void CasteRx1::computeENUcovs()
+{
+	double auxM[3][3];
+	int ii;
+
+	//compute covariance matrix
+	//firts step: auxM=TMenu*covEcef
+	for(ii=0;ii<3;ii++)
+	{
+		auxM[ii][0]=TMenu[ii][0]*cxxWgs+TMenu[ii][1]*cxyWgs+TMenu[ii][2]*cxzWgs;
+		auxM[ii][1]=TMenu[ii][0]*cxyWgs+TMenu[ii][1]*cyyWgs+TMenu[ii][2]*cyzWgs;
+		auxM[ii][2]=TMenu[ii][0]*cxzWgs+TMenu[ii][1]*cyzWgs+TMenu[ii][2]*czzWgs;
+	}
+	//second step: covMap = auxM*TMenu^T
+	cxxEnu=auxM[0][0]*TMenu[0][0]+auxM[0][1]*TMenu[0][1]+auxM[0][2]*TMenu[0][2];
+	cyyEnu=auxM[1][0]*TMenu[1][0]+auxM[1][1]*TMenu[1][1]+auxM[1][2]*TMenu[1][2];
+	czzEnu=auxM[2][0]*TMenu[2][0]+auxM[2][1]*TMenu[2][1]+auxM[2][2]*TMenu[2][2];
+	cxyEnu=auxM[0][0]*TMenu[1][0]+auxM[0][1]*TMenu[1][1]+auxM[0][2]*TMenu[1][2];
+	cxzEnu=auxM[0][0]*TMenu[2][0]+auxM[0][1]*TMenu[2][1]+auxM[0][2]*TMenu[2][2];
+	cyzEnu=auxM[1][0]*TMenu[2][0]+auxM[1][1]*TMenu[2][1]+auxM[1][2]*TMenu[2][2];
+}
+
+void CasteRx1::markBlockAsReceived(unsigned short int id)
+{
+	list<sbfBlockManager>::iterator iiBlock;	
+	
+	for (iiBlock=blockList.begin();iiBlock!=blockList.end();iiBlock++)
+	{ 
+		if ( iiBlock->blockId == id ) iiBlock->received = true;
+	}
+}
diff --git a/src/asterx1_gps.h b/src/asterx1_gps.h
new file mode 100644
index 0000000000000000000000000000000000000000..77701d61ce6872a7246ee158b901ab1ca7feb073
--- /dev/null
+++ b/src/asterx1_gps.h
@@ -0,0 +1,400 @@
+
+#ifndef asterx1_gps_h
+#define asterx1_gps_h
+
+//include
+#include <iostream>
+#include <list>
+#include <math.h>
+#include "rs232.h"
+#include "eventserver.h"
+#include "commexceptions.h"
+#include "eventexceptions.h"
+#include <time.h>
+#include <sys/time.h>
+
+using namespace std;
+
+/* Look up table for fast computation of the CCITT 16-bit CRC. */
+static const unsigned short CRC_16CCIT_LookUp[256] = {
+  0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 
+  0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 
+  0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 
+  0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 
+  0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 
+  0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 
+  0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 
+  0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 
+  0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 
+  0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 
+  0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 
+  0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 
+  0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 
+  0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 
+  0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 
+  0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 
+  0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 
+  0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 
+  0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 
+  0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 
+  0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 
+  0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 
+  0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 
+  0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 
+  0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 
+  0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 
+  0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 
+  0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 
+  0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 
+  0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 
+  0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 
+  0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
+
+union uniFloat {
+  float flt;
+  unsigned int i;
+};
+
+union uniDouble {
+  double dbl;
+  unsigned long long int i;
+};
+
+struct sbfBlockManager {
+  unsigned short int blockId;
+  bool received;
+};
+
+struct asterx1DeviceConfig {
+  string portName; //serial port system name 
+  string acqPeriod; //string indicating acquisition period. Takes one of the values of the vector "acqPeriodValues"
+};
+
+//physical constants
+const double EARTH_RADIUS = 6378137.0;
+const double EARTH_EXCENTRICITY = 0.081819190842622; 
+
+//Device protocol constants (SBF protocol)
+const unsigned short int PVTCartesian_ID = 4006;
+const unsigned short int PVTGeodetic_ID = 4007;
+const unsigned short int PosCovCartesian_ID = 5905;
+const unsigned short int DOP_ID = 4001;
+
+//acquisition constants
+const unsigned int ASTERX_BAUDRATE = 115200;
+const int DATA_TIMEOUT = 11000; //msec
+const int CONFIG_TIMEOUT = 500; //msec
+const string acqPeriodValues[] = {"onChange","msec20","msec50","msec100","msec200","msec500","sec1","sec2","sec5","sec10"};
+enum acqPeriodValuesIndex {ONCHANGE = 0, MSEC20, MSEC50, MSEC100, MSEC200, MSEC500, SEC1, SEC2, SEC5, SEC10};
+
+//data sizes
+const unsigned int BLOCK_HEADER_SIZE = 8;
+const unsigned int MIN_BLOCK_SIZE = BLOCK_HEADER_SIZE +1;
+const unsigned int MAX_BLOCK_SIZE = 200;
+
+/**
+  Member functions that returns an integer associated to success or not, should return one of these values
+*/
+const int BASIC_SUCCESS = 1;
+const int PORT_OPEN_ERROR = -1;
+const int PORT_CLOSE_ERROR = -2;
+const int PORT_CONFIG_ERROR = -3;
+const int ASTERX_CONFIG_ERROR = -4;
+const int ASTERX1_INVALID_COMMAND = -5;
+const int ASTERX1_STOPPINTG_ERROR = -6;
+const int PORT_READ_TIMEOUT = -7;
+const int ACQUISITION_ERROR = -8;
+
+/**
+  Status of a class object is a bitwise OR of different values. The given bit is set when positive cases, and reset if negative significance
+*/
+const unsigned int DEVICE_OPEN = 0x1;
+const unsigned int ACQUISITION_RUNNING = 0x2;
+const unsigned int DATA_BLOCK_OK = 0x4;
+const unsigned int GPS_AVAILABLE = 0x8;
+const unsigned int ALL_OK = DEVICE_OPEN | ACQUISITION_RUNNING | DATA_BLOCK_OK | GPS_AVAILABLE;
+
+//unit identifiers
+const bool inRADS = 0;
+const bool inDEGREES = 1;
+
+/**
+  CasteRx1 implements continuous data acquisition from the asteRx1 GPS receiver. 
+  Serial communications are implemented by the class CRS232, inherited from CComm (both belonging to IRI communication library)
+  Detailed documentation about SBF data transfer protocol can be found in the device manual.
+  PLEASE NOTE: This driver only implements a part of the AsteRx1 device functionalities (the most useful part for mobile robot navigation).
+  PLEASE NOTE: For extended functionalities , please refer to the manual.
+  Programmer: Andreu Corominas Murtra, acorominas@iri.upc.edu
+  Device website: www.septentrio.com
+*/
+class CasteRx1
+{
+	public:
+		/**
+		  Constructor: just catch the name of the serial port
+		*/
+		CasteRx1(const string & hwPortName = "/dev/ttyACM0", const int acqRateIndex = MSEC500); 
+		
+		/**
+		  Destructor: Stops acquisition in case it was running and closes serial Port in case it was opened.
+		*/
+		virtual ~CasteRx1(); 
+				
+		/**
+		  Opens serial communications and starts serial comm thread.
+		  If success , sets status bit DEVICE_OPEN.
+		  Return values are:
+			BASIC_SUCCESS
+			PORT_OPEN_ERROR if thread can't be created or port can't be opened
+			PORT_CONFIG_ERROR if port can't be configured
+		*/
+		int openDevice(int xx=3); 
+		
+		/**
+		  Closes serial comm's , stops comm thread and deletes comm object.
+		  If success , resets status bit DEVICE_OPEN.
+		  Return values are:
+			BASIC_SUCCESS 
+			PORT_CLOSE_ERROR
+		*/
+		int closeDevice();
+		
+		/**
+		  Configures the device to perform some signal processing basics for mobile robotics.
+		  Starts a mode of operation of continuos data flow from the device at a rate of 2Hz.
+		  Return values are:
+			BASIC_SUCCESS
+			ASTERX_CONFIG_ERROR
+		*/
+		int startAcquisition(); 
+		
+		/**
+		  Stops mode of operation of continuous data flow
+		  Return values are:
+			BASIC_SUCCESS when device stop is ok
+			ASTERX1_STOPPINTG_ERROR otherwise.
+		*/ 
+		int stopAcquisition(); 
+		
+		/**
+		  Reads current data produced by the device. Ends when all data blocks requested have been received. 
+		  Sets status and all data fields. 
+		  Return values are:
+			BASIC_SUCCESS if all blocks are successfully decodes.
+			ACQUISITION_ERROR otherwise.
+		  Afterwards, call getStatus() to check for gps availability.
+		*/
+		int readDataFromDevice(); 
+		
+		/**
+		  Prints all current data in a single row of the given ostream (cout or file)
+		*/
+		void printData(ostream & ost);		
+		
+		/**
+		  Sets map origin and computes transformation matrix. 
+		  Angles in degrees and altitude in meters.
+		  A call to this function is mandatory if local coordinate related position is required.
+		*/
+		void setMapOrigin(double mapLat0, double mapLon0, double mapAlt0, double mapAlpha0); 
+		
+		/**
+		  Sets serial port name
+		*/
+		void setPortName(string pName);
+
+		/**
+		  Sets acquisition rate as on of the rateId indicated by the acqPeriodValuesIndex enum variable
+		*/
+		void setAcquisitionRate(int rateIndex);
+		
+		/**
+		  Prints the homogeneous transformation matrix used to convert data from ECEF-WGS to local map.
+		*/
+		void printTM(); 
+		
+		/**
+		  Get data ...
+		  TimeStamp is set by the computer running the driver.
+		  Tow is the GPS "time of week".
+		  PVTerror codes are explained in the device manual, pag XX.
+		  Lat and Lon are expressed in radians by default. Pass "inDEGREES" if degree values are required.
+		  *Wgs is data with respect to the ECEF-WGS coordinate frame.
+		  *Map is data with respect to the local (map) coordinate frame.
+		*/
+		unsigned int getStatus();
+		double getTimeStamp();
+		unsigned short int getWnc();
+		unsigned int getTow();
+		unsigned int getNumSatellites();
+		float getPDOP();
+		float getTDOP();
+		float getHDOP();
+		float getVDOP();
+		float getUndulation();
+		unsigned short int getPVTerror();
+		double getLat(bool units=inRADS); 
+		double getLon(bool units=inRADS); 
+		double getAlt();
+		double getXWgs();
+		double getYWgs();
+		double getZWgs();
+		double getXMap();
+		double getYMap();
+		double getZMap();
+		double getVxWgs();
+		double getVyWgs();
+		double getVzWgs();
+		double getVxMap();
+		double getVyMap();
+		double getVzMap();
+		double getCxxWgs();
+		double getCyyWgs();
+		double getCzzWgs();
+		double getCxyWgs();
+		double getCxxMap();
+		double getCyyMap();
+		double getCzzMap();
+		double getCxyMap();
+		double getCxxEnu();
+		double getCyyEnu();
+		double getCzzEnu();
+		double getCxyEnu();
+		double getCxzEnu();
+		double getCyzEnu();		
+		
+	protected:
+		CRS232 *serialPort; /**<Object for serial comms. This object launch an independent thread managing byte I/O through serial port (USB or RS232)*/
+		asterx1DeviceConfig config; /**<Devices configuration. Currently a single string with serial port name*/
+
+		//variables for device operation and configuration
+		unsigned int status;/**<Status related to the execution of this process*/
+		list<sbfBlockManager> blockList; /**<this list manages which data blocks are requested and has been (or not) received in the current iteration*/
+		double lat0, lon0, alt0, alpha0; /**<coordinates of the map origin. Alpha is the orientation of the north vector wrt the map X axis*/
+		double TM[4][4]; /**homogeneous transformation matrix to convert from ecef-wgs84 to map coordinates*/
+		double TMenu[3][3]; /**Rotation transformation matrix to convert from ecef-wgs84 to local tangential ENU (east north up) coordinates. Useful to output covariances following current ENU axis*/
+		
+		//GPS data to be published
+		double timeStamp; /**<time stamp set by the computer executing the process (not GPS time)*/
+		unsigned short int wnc; /**<gps week number*/		
+		unsigned int tow; /**<gps time of week in milliseconds*/
+		unsigned int numSatellites; /**<number of visible satellites*/
+		double PDOP, TDOP, HDOP, VDOP; /**<Dillution of precsion DOP's*/
+		double undulation; /**<local geoid undulation between Datum ellipsoide and reference geoide*/
+		unsigned short int pvtError; /**<error codes related to GPS position computation. (see page 50 of Firmware User Manual)*/
+		double lat, lon, alt; /**<position in geodetic frame*/
+		double xWgs, yWgs, zWgs; /**<position in WGS frame*/
+		double xMap, yMap, zMap; /**<position in Map frame, a given reference frame*/
+		double vxWgs,vyWgs,vzWgs; /**<velocities referred to WGS*/
+		double vxMap, vyMap, vzMap; /**<velocities in Map frame, a given reference frame*/
+		double cxxWgs,cyyWgs,czzWgs,cxyWgs,cxzWgs,cyzWgs; /**<covariance parameters of WGS position*/
+		double cxxMap, cyyMap, czzMap, cxyMap; /**<covariance parameters in Map frame, a given reference frame*/
+		double cxxEnu,cyyEnu,czzEnu,cxyEnu,cxzEnu,cyzEnu; /**<covariance parameters in the local tangential plane of the current position following the East North Up axis*/				
+
+		/**
+		  Reads nn bytes from the serial communication. If there are no bytes available, this function blocks up to timeout is reached.
+		  Success when ALL bytes have been received, it returns BASIC_SUCCESS
+		  If timeout, it returns PORT_READ_TIMEOUT.
+		*/
+		int readNbytes(unsigned char *buffer, unsigned int nn, unsigned int msecTimeOut);
+		
+		/**
+		  Synchronizes data reading with a given header mark. (markSixe in bytes).
+  		  Return values are:
+				BASIC_SUCCESS if success: the mark is found at the ffdd file descriptor input
+				PORT_READ_TIMEOUT if timeout is reached and the mark is not found
+		*/
+		int synchronizeHeader(const unsigned char *mark, int msecTimeOut=1000, unsigned int markSize=2);
+		
+		/**
+		  Sends a command to the AsteRx1 device. 
+		  Return values are :
+				BASIC_SUCCESS if device has acknowledged the command.
+				PORT_READ_TIMEOUT if timeout is reached and the receiver has not replied with an acknowledment.
+				ASTERX1_INVALID_COMMAND when device doesn't know the command.
+				ASTERX_CONFIG_ERROR otherwise.
+		*/
+		int sendCommand(const string & cmnd); 
+		
+		/**
+		  Returns 1 byte integer in buffer (little-endian reading)
+		*/
+		unsigned short int getUI1(unsigned char *buf); 
+
+		/**
+		  Returns 2 bytes integer in buffer (little-endian reading)
+		*/
+		unsigned short int getUI2(unsigned char *buf);
+		
+		/**
+		  Returns 4 bytes integer in buffer (little-endian reading)
+		*/		
+		unsigned int getUI4(unsigned char *buf);
+		
+		/**
+		  Returns 4 byte float in buffer (little-endian reading)
+		*/
+		float getFloat(unsigned char *buf);
+		
+		/**
+		  Returns 8 byte float in buffer (little-endian reading)
+		*/
+		double getDouble(unsigned char *buf);
+
+		/**
+		  Decodes PVTCartesian data block. Implementation of the SBF data transfer protocol.
+		*/
+		int decodePVTCartesian(unsigned char *sbfMsg);
+		
+		/**
+		  Decodes PVTGeodetic data block. Implementation of the SBF data transfer protocol.
+		*/		
+		int decodePVTGeodetic(unsigned char *sbfMsg);
+		
+		/**
+		  Decodes PosCovCartesian data block. Implementation of the SBF data transfer protocol.
+		*/		
+		int decodePosCovCartesian(unsigned char *sbfMsg);
+		
+		/**
+		  Decodes DOP data block. Implementation of the SBF data transfer protocol.
+		*/		
+		int decodeDOP(unsigned char *sbfMsg);
+		
+		/**
+		  computes the crc-ccitt of buf with polynomic 0x1021
+		*/
+		//unsigned short int computeCrc(unsigned char *buf, unsigned short int nBytes);
+		//unsigned short int CRC_compute16CCITT(const void * buf, size_t buf_length);
+		unsigned short int CRC_compute16CCITT(unsigned char *buf, unsigned short int nBytes);
+		
+		/**
+		  Computes the matrix to transform positions from ECEF-WGS to a local coordinate frame.
+		  Local coordinate frame origin should be set by public function setMapOrigin().
+		*/
+		void computeTM();
+
+		/**
+		  Computes the matrix to transform positions from ECEF-WGS to the local tangential plane of the current position folloing the East North Up (ENU) axis
+		  This matris is useful to output a covariance matrix of the WGS position following the ENU local tangential coordinates
+		*/
+		void computeTMenu();
+		
+		/**
+		  Transforms ECEF-WGS positions, velocities and covariances to local coordinate frame.
+		  Local coordinate frame origin shouold be set by public function setMapOrigin().
+		*/			
+		void fromWgsToMap(); 
+		
+		/**
+		  Computes covariance elements of the position referenced to the ENU axis of the current local tangential plane
+		*/
+		void computeENUcovs();
+		
+		/**
+		  Sets to true the received field of the member in blockList that have blockId = id
+		*/
+		void markBlockAsReceived(unsigned short int id); 
+};
+#endif
diff --git a/src/asterx1exceptions.cpp b/src/asterx1exceptions.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..48601198744d9cc9711f1f338fbadb7080bde1c7
--- /dev/null
+++ b/src/asterx1exceptions.cpp
@@ -0,0 +1,28 @@
+// Copyright (C) 2010 Institut de Robòtica i Informàtica Industrial, CSIC-UPC.
+// Author Martí Morta (mmorta@iri.upc.edu)
+// All rights reserved.
+//
+// This is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "hokuyoexceptions.h"
+#include <string.h>
+#include <stdio.h>
+
+const std::string hokuyo_exception_msg="[CHokuyo class] - ";
+
+CHokuyoException::CHokuyoException(const std::string& where,const std::string& error_msg):CException(where,hokuyo_exception_msg)
+{
+  this->error_msg+=error_msg;
+}
+
diff --git a/src/asterx1exceptions.h b/src/asterx1exceptions.h
new file mode 100644
index 0000000000000000000000000000000000000000..0971abbae344f0932daa19ba294ed6f5646eeda5
--- /dev/null
+++ b/src/asterx1exceptions.h
@@ -0,0 +1,65 @@
+// Copyright (C) 2009-2010 Institut de Robòtica i Informàtica Industrial, CSIC-UPC.
+// Author Martí Morta  (mmorta@iri.upc.edu)
+// All rights reserved.
+//
+// This file is part of iriutils
+// iriutils is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef _HOKUYO_EXCEPTIONS
+#define _HOKUYO_EXCEPTIONS
+
+#include "exceptions.h"
+
+/**
+ * \brief Mutual exclusion exception class
+ *
+ * This class implements the exceptions for the CMutex class. It does not add
+ * any feature to the base clase CException, but it is implemented to easyly 
+ * distinguish between different types of exceptions.
+ *
+ * In addition to the general exception message added by the base class, this
+ * class adds the "[CHokuyo class] - " string to the user message to identify
+ * the class that generated the exception.
+ *
+ */
+class CHokuyoException : public CException
+{
+  public:
+    /**
+     * \brief Constructor
+     *
+     * The constructor calls the base class constructor to add the general
+     * exception identifier and then adds the class identifier string 
+     * "[CHokuyo class]" and the supplied error message. The total exception
+     * message will look like this:
+     *
+     * \verbatim
+     * [Exception caught] - <where>
+     * Error: [CHokuyo class] - <error message>
+     * \endverbatim
+     *
+     * \param where a null terminated string with the information about the name
+     *              of the function, the source code filename and the line where
+     *              the exception was generated. This string must be generated 
+     *              by the _HERE_ macro.
+     *
+     * \param error_msg a null terminated string that contains the error message.
+     *                  This string may have any valid character and there is no
+     *                  limit on its length.
+     */ 
+    CHokuyoException(const std::string& where,const std::string& error_msg);
+};
+
+#endif
+
diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4d441f04b0b93d008f512c254c2524531b018fdd
--- /dev/null
+++ b/src/examples/CMakeLists.txt
@@ -0,0 +1,9 @@
+# edit the following line to add the source code for the example and the name of the executable
+ADD_EXECUTABLE(testasterx1 testasterx1.cpp)
+
+# edit the following line to add the necessary libraries
+TARGET_LINK_LIBRARIES(testasterx1 asterx1_gps)
+
+#fast building
+# ADD_EXECUTABLE(testasterx1 testasterx1.cpp ../asterx1.cpp)
+
diff --git a/src/examples/testasterx1.cpp b/src/examples/testasterx1.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0ef7afd7dab8a5f1fa0a8c619a7f9e605579acc8
--- /dev/null
+++ b/src/examples/testasterx1.cpp
@@ -0,0 +1,134 @@
+/*! \example testasterx1.cpp
+
+In this example almost all driver functionalities are tested.
+
+\b Usage:
+
+USB Default case (just one device which uses ttyACM connected)
+\code
+./testasterx1
+\endcode
+
+USB any port
+\code
+./testasterx1 [-u DEVICEPORT (/dev/ttyACM0)] [-n NUMITERATIONS]
+\endcode
+ */
+
+#include <stdlib.h>
+#include <asterx1_gps.h>
+
+using namespace std;
+
+int main(int argc, char **argv)
+{
+	int opt;
+	int ii;
+	int retValue;
+	int nIterations = 10;
+	int rate = MSEC500; //ONCHANGE, MSEC20, ... , MSEC100, ... SEC1, SEC5
+	string serial_device="/dev/ttyACM0";
+	streamsize tsDigits;
+	CasteRx1 *myGps;
+  
+	cout << "\n\n    TEST AsteRx1 GPS RECEIVER     \n\n" << endl;
+
+	//cout << "acqPeriodValues[ONCHANGE]: " << acqPeriodValues[ONCHANGE] << endl;
+	
+	// Argument management
+	while ((opt = getopt(argc, argv, "u:n:r:h?"))!= -1)
+	{
+		switch (opt)
+		{
+			case 'u': // change USB device
+				serial_device = optarg;
+				break;
+			case 'n':
+				nIterations = atoi(optarg);
+				break;
+			case 'r':
+				rate = atoi(optarg);
+				break;
+			case '?': // help
+			case 'h':
+			default:
+				cout << "  USAGE" << endl
+				<< "  " << argv[0] << " [options]" << endl
+				<< "  OPTIONS" << endl
+				<< "   -u SERIAL_DEVICE (default: " << serial_device << ")" << endl
+				<< "   -n NUMBER OF ITERATIONS (default: " << nIterations << ")" << endl
+				<< "   -r ACQUISITION RATE: (default: " << rate << ")" << endl;
+				for (ii=0; ii<10; ii++)
+				{
+					cout << "		" << ii << ": " << acqPeriodValues[ii] << endl;
+				}
+				cout << endl;
+				return 1;
+		}
+	}
+	
+	myGps = new CasteRx1(serial_device,rate);
+
+	myGps->setMapOrigin(41.388595, 2.113133, 120, 44.2); //sets map origin for coordinate transformation
+	//myGps->printTM(); //prints to stdout the transformation matrix
+
+	retValue = myGps->openDevice();//open device comm's
+	
+	retValue = myGps->closeDevice();//close device comm's (stressing tests ...)
+	retValue = myGps->openDevice();//open device comm's, again
+	
+	myGps->setPortName("/dev/ttyS1"); //checking that when device is open, port configuration can't be achieved
+	myGps->setAcquisitionRate(56); //checking that when invalid rate indexes prdouces an error and don't change the rate
+	myGps->setAcquisitionRate(SEC2); //checking that when device is open rate configuration can be achieved
+	myGps->setAcquisitionRate(rate); //checking that when device is open rate configuration can be achieved
+	
+	if ( retValue == BASIC_SUCCESS )
+	{
+		retValue = myGps->startAcquisition();//start data acquisition 
+		retValue = myGps->stopAcquisition();//stop data acquisition (stressing tests ...)
+		retValue = myGps->startAcquisition();//start data acquisition, again
+		if ( retValue == BASIC_SUCCESS )
+		{
+			for (ii=0; ii<nIterations; ii++)
+			{
+				cout << endl;
+				myGps->readDataFromDevice();
+				//myGps->printData(cout); //prints to cout all current data in a single row. (cout can be repolaced by another ostream object reference)
+				cout << "Status = " << myGps->getStatus() << endl;
+				tsDigits=cout.precision(12);
+				cout << "TimeStamp = " << myGps->getTimeStamp() << endl;
+				cout.precision(tsDigits);
+				cout << "PVT error = " << myGps->getPVTerror() << endl;
+				cout << "TOW = " << myGps->getTow() << endl;
+				
+				if ( myGps->getStatus() == ALL_OK )
+				{
+					cout << "Num Of Satellites = " << myGps->getNumSatellites() << endl;
+					tsDigits=cout.precision(12);
+					cout << "lat = " << myGps->getLat(inDEGREES) << endl;
+					cout << "lon = " << myGps->getLon(inDEGREES) << endl;
+					cout.precision(tsDigits);
+					cout << "alt = " << myGps->getAlt() << endl;
+					cout << "xWgs = " << myGps->getXWgs() << endl;
+					cout << "yWgs = " << myGps->getYWgs() << endl;
+					cout << "zWgs = " << myGps->getZWgs() << endl;
+					cout << "xMap = " << myGps->getXMap() << endl;
+					cout << "yMap = " << myGps->getYMap() << endl;
+					cout << "zMap = " << myGps->getZMap() << endl;
+					cout << "vxMap = " << myGps->getVxMap() << endl;
+					cout << "vyMap = " << myGps->getVyMap() << endl;
+					cout << "vzMap = " << myGps->getVzMap() << endl;
+					cout << "PDOP = " << myGps->getPDOP() << endl;
+				}
+			}
+			
+			retValue = myGps->stopAcquisition();
+		}
+		
+		retValue = myGps->closeDevice();
+	}
+
+	delete myGps;
+	
+	return 0;
+}