[Pkg-running-devel] [openambit] 21/23: Imported Upstream version 0.4

Christian Perrier bubulle at moszumanska.debian.org
Sat Jul 1 19:36:29 UTC 2017


This is an automated email from the git hooks/post-receive script.

bubulle pushed a commit to branch master
in repository openambit.

commit c54c26e7d3c41b0fee2487e52b98a1f2a42b1b53
Author: Christian Perrier <bubulle at debian.org>
Date:   Tue May 2 19:10:05 2017 +0200

    Imported Upstream version 0.4
---
 .gitignore                                         |  29 +
 CMakeLists.txt                                     |   3 +
 README.rst                                         |  22 +-
 src/libambit/CMakeLists.txt                        |   5 +-
 src/libambit/device_driver.h                       |   5 +
 src/libambit/device_driver_ambit.c                 |  59 +-
 src/libambit/device_driver_ambit3.c                |  12 +-
 src/libambit/device_driver_ambit_navigation.c      | 481 +++++++++++++++
 src/libambit/device_driver_ambit_navigation.h      | 140 +++++
 src/libambit/distance.c                            |  58 ++
 src/libambit/distance.h                            |  44 ++
 src/libambit/libambit.c                            | 312 ++++++++++
 src/libambit/libambit.h                            | 342 ++++++++++-
 src/libambit/pmem20.c                              |  45 +-
 src/libambit/pmem20.h                              |   2 +
 src/libambit/protocol.c                            |   2 +-
 src/libambit/protocol.h                            |   7 +-
 src/libambit/sport_mode_serialize.c                | 459 ++++++++++++++
 src/libambit/sport_mode_serialize.h                |  69 +++
 src/movescount/CMakeLists.txt                      |  37 +-
 src/movescount/logentry.h                          |   4 -
 src/movescount/logstore.cpp                        |   4 +-
 src/movescount/movescount.cpp                      | 303 +++++++++-
 src/movescount/movescount.h                        |  16 +-
 src/movescount/movescountjson.cpp                  | 492 +++++++++++++++-
 src/movescount/movescountjson.h                    |  20 +-
 src/movescount/movescountsettings.cpp              |  70 +++
 src/movescount/movescountsettings.h                |  31 +
 src/movescount/movescountxml.cpp                   |   2 +-
 src/movescount/sportmode.cpp                       | 443 ++++++++++++++
 src/movescount/sportmode.h                         | 149 +++++
 src/movescount/sportmodegroup.cpp                  |  77 +++
 src/movescount/sportmodegroup.h                    |  46 ++
 src/openambit/CMakeLists.txt                       | 114 ++--
 src/openambit/deployment/openambit.appdata.xml     |  25 +
 src/openambit/devicemanager.cpp                    |  67 ++-
 src/openambit/devicemanager.h                      |   4 +-
 src/openambit/main.cpp                             |  16 +-
 src/openambit/mainwindow.cpp                       |  53 +-
 src/openambit/mainwindow.h                         |   3 +-
 src/openambit/mainwindow.ui                        |  33 ++
 src/openambit/settingsdialog.cpp                   |   4 +
 src/openambit/settingsdialog.ui                    |  18 +-
 src/openambit/translations/openambit_de.ts         |  38 +-
 .../{openambit_de.ts => openambit_nb_NO.ts}        | 245 ++++----
 tools/openambit2gpx.py                             |   9 +-
 wireshark_dissector/CMakeLists.txt                 |   5 +-
 wireshark_dissector/ambit-dissector.c              | 656 ++++++++++++++++++++-
 wireshark_dissector/tools/make-dissector-reg.py    |  15 +-
 49 files changed, 4821 insertions(+), 274 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5b94d3c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,29 @@
+# Ignore build directories
+*build*/
+
+# Ignore temporary and user files
+*~
+*.user
+
+# Ignore in-tree build artifacts
+CMakeCache.txt
+CMakeFiles/
+cmake_install.cmake
+Makefile
+moc_*.cpp
+*_automoc.cpp
+/src/example/ambitconsole
+/src/libambit/libambit.a
+/src/libambit/libambit.so*
+/src/movescount/libmovescount.a
+/src/movescount/libmovescount.so*
+/src/openambit/moc_*.cxx
+/src/openambit/moc_*.cxx_parameters
+/src/openambit/openambit
+/src/openambit/openambit_*.qm
+/src/openambit/qrc_*.cxx
+/src/openambit/ts.qrc
+/src/openambit/ui_*.h
+/src/openambit/*.qrc.depends
+/wireshark_dissector/ambit.so
+/wireshark_dissector/plugin.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 466186f..2e1cee0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,6 +22,9 @@ cmake_minimum_required(VERSION 3.0)
 project(Openambit
   LANGUAGES NONE)
 
+option(USE_QT5 "Build against Qt5" OFF)
+option(BUILD_EXTRAS "Build examples and wireshark dissector" OFF)
+
 add_subdirectory(src/libambit)
 add_subdirectory(src/movescount)
 add_subdirectory(src/openambit)
diff --git a/README.rst b/README.rst
index 6ceabdb..dffe18f 100644
--- a/README.rst
+++ b/README.rst
@@ -15,11 +15,11 @@ Modules
 Openambit includes the following modules:
 
 src/libambit
-  a library that let's you computer communicate with your Ambit watch
+  a library that let's your computer communicate with your Ambit watch.
 
 src/openambit
   a Qt based GUI application to get data off your watch and push it to
-  Suunto's `Movescount`_ site
+  Suunto's `Movescount`_ site.
 
 src/example
   a very simple command-line application that reports on your watch's
@@ -29,7 +29,7 @@ src/example
 tools
   contains a few utilities that people thought useful.  One compares
   Openambit's XML log files with those from `Moveslink2`_ and another
-  converts the XML to `GPX`_
+  converts the XML to `GPX`_.
 
 wireshark_dissector
   a `Wireshark`_ packet dissector to help reverse engineer the Ambit
@@ -82,7 +82,7 @@ Build Procedure
 The simplest way to build from source is by means of the ``build.sh``
 script.  It will build all components needed to use Openambit.  Any
 command-line arguments you specify are passed on to ``cmake``.  That
-means you can set up a "Debug" build with
+means you can set up a "Debug" build with:
 
 .. code-block:: sh
 
@@ -90,14 +90,14 @@ means you can set up a "Debug" build with
    ./build.sh -DCMAKE_BUILD_TYPE=Debug
 
 Developer and otherwise inquisitive types may want to build some of
-the extras that are included.  To do so
+the extras that are included.  To do so:
 
 .. code-block:: sh
 
    cd /path/to/your/clone/of/openambit
    BUILD_EXTRAS=1 ./build.sh
 
-You can run the applications you built *without* installing as follows
+You can run the applications you built *without* installing as follows:
 
 .. code-block:: sh
 
@@ -107,7 +107,7 @@ You can run the applications you built *without* installing as follows
 
 If you are only interested in building a selected module, you can just
 use ``cmake`` directly.  For example, if all you really want to build
-is ``libambit`` and nothing else, you could (for example)
+is ``libambit`` and nothing else, you could (for example):
 
 .. code-block:: sh
 
@@ -118,7 +118,7 @@ is ``libambit`` and nothing else, you could (for example)
    make
 
 Actually, you can also build everything directly with ``cmake``.  The
-following ought to work
+following ought to work:
 
 .. code-block:: sh
 
@@ -134,14 +134,14 @@ Install Procedure
 If you have built from source with ``build.sh``, you can install with
 ``install.sh``.  This only installs the ``openambit`` application and
 the ``libambit`` library it needs.  When you have built only selected
-parts, simply install them with
+parts, simply install them with:
 
 .. code-block:: sh
 
    cd /path/to/your/build/directory
    sudo make install
 
-If you built directly with ``cmake``, installation is simply
+If you built directly with ``cmake``, installation is simply:
 
 .. code-block:: sh
 
@@ -152,7 +152,7 @@ If you built directly with ``cmake``, installation is simply
 To enable the Wireshark dissector, just copy the ``ambit.so`` file to
 your ``~/.wireshark/plugins/`` directory.  You can also put a symbolic
 link there pointing to the build result so your next ``wireshark`` run
-will use the latest, greatest(?) version.
+will use the latest and greatest(?) version.
 
 
 .. _Movescount: http://www.movescount.com/
diff --git a/src/libambit/CMakeLists.txt b/src/libambit/CMakeLists.txt
index 93b5042..8cffec7 100644
--- a/src/libambit/CMakeLists.txt
+++ b/src/libambit/CMakeLists.txt
@@ -24,9 +24,11 @@ add_library (
   crc16.c
   debug.c
   device_driver_ambit.c
+  device_driver_ambit_navigation.c
   device_driver_ambit3.c
   device_driver_common.c
   device_support.c
+  distance.c
   libambit.c
   personal.c
   pmem20.c
@@ -34,6 +36,7 @@ add_library (
   sbem0102.c
   sha256.c
   utils.c
+  sport_mode_serialize.c
   ${HIDAPI_SOURCE_FILES}
 )
 
@@ -43,7 +46,7 @@ target_link_libraries(
   m
 )
 
-set_target_properties(ambit PROPERTIES VERSION 0.3.0 SOVERSION 0)
+set_target_properties(ambit PROPERTIES VERSION 0.4.0 SOVERSION 0)
 
 include_directories(
   ${HIDAPI_INCLUDE_DIR}
diff --git a/src/libambit/device_driver.h b/src/libambit/device_driver.h
index 28e800b..bf8b65c 100644
--- a/src/libambit/device_driver.h
+++ b/src/libambit/device_driver.h
@@ -26,6 +26,7 @@
 #include <stdint.h>
 
 #include "libambit.h"
+#include "device_driver_ambit_navigation.h"
 
 typedef struct ambit_device_driver_s {
     void (*init)(ambit_object_t *object, uint32_t driver_param);
@@ -37,6 +38,10 @@ typedef struct ambit_device_driver_s {
     int (*log_read)(ambit_object_t *object, ambit_log_skip_cb skip_cb, ambit_log_push_cb push_cb, ambit_log_progress_cb progress_cb, void *userref);
     int (*gps_orbit_header_read)(ambit_object_t *object, uint8_t data[8]);
     int (*gps_orbit_write)(ambit_object_t *object, uint8_t *data, size_t datalen);
+    int (*navigation_read)(ambit_object_t *object, ambit_personal_settings_t *settings);
+    int (*navigation_write)(ambit_object_t *object, ambit_personal_settings_t *settings);
+    int (*sport_mode_write)(ambit_object_t *object, ambit_sport_mode_device_settings_t *ambitCustomModes);
+    int (*app_data_write)(ambit_object_t *object, ambit_sport_mode_device_settings_t *ambitCustomModes, ambit_app_rules_t* ambit_apps);
 } ambit_device_driver_t;
 
 extern ambit_device_driver_t ambit_device_driver_ambit;  // Ambit & Ambit2
diff --git a/src/libambit/device_driver_ambit.c b/src/libambit/device_driver_ambit.c
index c17a963..c2f348e 100644
--- a/src/libambit/device_driver_ambit.c
+++ b/src/libambit/device_driver_ambit.c
@@ -21,15 +21,19 @@
  */
 #include "device_driver.h"
 #include "device_driver_common.h"
+#include "device_driver_ambit_navigation.h"
 #include "libambit_int.h"
 #include "protocol.h"
 #include "pmem20.h"
 #include "personal.h"
+#include "sport_mode_serialize.h"
 #include "debug.h"
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+
 /*
  * Local definitions
  */
@@ -50,6 +54,9 @@ static int log_read(ambit_object_t *object, ambit_log_skip_cb skip_cb, ambit_log
 static int gps_orbit_header_read(ambit_object_t *object, uint8_t data[8]);
 static int gps_orbit_write(ambit_object_t *object, uint8_t *data, size_t datalen);
 
+static int sport_mode_write(ambit_object_t *object, ambit_sport_mode_device_settings_t *ambit_sport_modes);
+static int app_data_write(ambit_object_t *object, ambit_sport_mode_device_settings_t *ambit_device_settings, ambit_app_rules_t* ambit_apps);
+
 /*
  * Global variables
  */
@@ -62,7 +69,11 @@ ambit_device_driver_t ambit_device_driver_ambit = {
     personal_settings_get,
     log_read,
     gps_orbit_header_read,
-    gps_orbit_write
+    gps_orbit_write,
+    ambit_navigation_read,
+    ambit_navigation_write,
+    sport_mode_write,
+    app_data_write
 };
 
 /*
@@ -135,6 +146,7 @@ static int log_read(ambit_object_t *object, ambit_log_skip_cb skip_cb, ambit_log
         LOG_WARNING("Failed to read number of log entries");
         return -1;
     }
+
     log_entries_total = le16toh(*(uint16_t*)(reply_data + 2));
     libambit_protocol_free(reply_data);
 
@@ -297,3 +309,48 @@ static int gps_orbit_write(ambit_object_t *object, uint8_t *data, size_t datalen
     return ret;
 }
 
+static int sport_mode_write(ambit_object_t *object, ambit_sport_mode_device_settings_t *ambit_device_settings)
+{
+    int ret = -1;
+
+    LOG_INFO("Writing Custom mode data");
+
+//    libambit_protocol_command(object, ambit_command_write_start, NULL, 0, NULL, NULL, 0);
+
+    int dataBufferSize = calculate_size_for_serialize_sport_mode_device_settings(ambit_device_settings);
+    if (dataBufferSize==0) {
+        return 0;
+    }
+
+    uint8_t *data = (uint8_t*)malloc(dataBufferSize);
+
+    if (data != NULL) {
+        int dataLen = serialize_sport_mode_device_settings(ambit_device_settings, data);
+        ret = libambit_pmem20_sport_mode_write(&object->driver_data->pmem20, data, dataLen, false);
+    }
+
+    return ret;
+}
+
+static int app_data_write(ambit_object_t *object, ambit_sport_mode_device_settings_t *ambit_device_settings, ambit_app_rules_t* ambit_apps)
+{
+    int ret = -1;
+
+    LOG_INFO("Writing App data");
+
+//    libambit_protocol_command(object, ambit_command_write_start, NULL, 0, NULL, NULL, 0);
+
+    int dataBufferSize = calculate_size_for_serialize_app_data(ambit_device_settings, ambit_apps);
+    if (dataBufferSize==0) {
+        return 0;
+    }
+
+    uint8_t *data = (uint8_t*)malloc(dataBufferSize);
+
+    if (data != NULL) {
+        int dataLen = serialize_app_data(ambit_device_settings, ambit_apps, data);
+        ret = libambit_pmem20_app_data_write(&object->driver_data->pmem20, data, dataLen, false);
+    }
+
+    return ret;
+}
diff --git a/src/libambit/device_driver_ambit3.c b/src/libambit/device_driver_ambit3.c
index 05011d9..0a7991c 100644
--- a/src/libambit/device_driver_ambit3.c
+++ b/src/libambit/device_driver_ambit3.c
@@ -51,7 +51,7 @@ struct ambit_device_driver_data_s {
         memory_map_entry_t routes;
         memory_map_entry_t rules;
         memory_map_entry_t gps;
-        memory_map_entry_t custom_modes;
+        memory_map_entry_t sport_modes;
         memory_map_entry_t training_program;
         memory_map_entry_t excercise_log;
         memory_map_entry_t event_log;
@@ -91,7 +91,11 @@ ambit_device_driver_t ambit_device_driver_ambit3 = {
     personal_settings_get,
     log_read,
     gps_orbit_header_read,
-    gps_orbit_write
+    gps_orbit_write,
+    NULL,
+    NULL,
+    NULL,
+    NULL
 };
 
 /*
@@ -386,7 +390,7 @@ static int get_memory_maps(ambit_object_t *object)
     memory_map_entry_t *mm_entry;
     const uint8_t *ptr;
 
-    if (libambit_protocol_command(object, ambit_command_unknown2, NULL, 0, &reply_data, &replylen, 2) != 0 || replylen < 4) {
+    if (libambit_protocol_command(object, ambit_command_waypoint_count, NULL, 0, &reply_data, &replylen, 2) != 0 || replylen < 4) {
         libambit_protocol_free(reply_data);
         LOG_WARNING("Failed to read memory map key");
         return -1;
@@ -416,7 +420,7 @@ static int get_memory_maps(ambit_object_t *object)
                 mm_entry = &object->driver_data->memory_maps.gps;
             }
             else if (strcmp((char*)ptr, "CustomModes") == 0) {
-                mm_entry = &object->driver_data->memory_maps.custom_modes;
+                mm_entry = &object->driver_data->memory_maps.sport_modes;
             }
             else if (strcmp((char*)ptr, "TrainingProgram") == 0) {
                 mm_entry = &object->driver_data->memory_maps.training_program;
diff --git a/src/libambit/device_driver_ambit_navigation.c b/src/libambit/device_driver_ambit_navigation.c
new file mode 100644
index 0000000..2381aeb
--- /dev/null
+++ b/src/libambit/device_driver_ambit_navigation.c
@@ -0,0 +1,481 @@
+/*
+ * (C) Copyright 2017 Lars Andre Landås
+ *
+ * This file is part of libambit.
+ *
+ * libambit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Contributors:
+ * Lars Andre Landås (landas at gmail.com)
+ * Kristoffer Tonheim (kristoffer.tonheim at gmail.com)
+ *
+ */
+
+#include "libambit.h"
+#include "device_driver_ambit_navigation.h"
+#include "protocol.h"
+#include "debug.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+const uint8_t ambit_waypoint_types_from_movescount[NUM_WAYPOINTS_MOVESCOUNT] = { 0,0,3,3,2,2,7,7,7,10,10,10,16,16,16,16,12,12,12,12,8,4,13,5,6,9,17,14,14,15,11,1,5,6 };
+const uint8_t ambit_waypoint_types_to_movescount[NUM_WAYPOINTS_AMBIT] = { 0,31,4,2,21,23,24,6,20,25,9,30,16,22,27,29,12,26 };
+
+int ambit_navigation_read(ambit_object_t *object, ambit_personal_settings_t *personal_settings) {
+
+    ambit_pack_waypoint_t *pack_data = NULL;
+    uint16_t ambit_pack_count = 0;
+    int ret = ambit_navigation_waypoint_read(object, &pack_data, &ambit_pack_count);
+
+    if(personal_settings->waypoints.data != NULL) {
+        free(personal_settings->waypoints.data);
+        personal_settings->waypoints.data = NULL;
+    }
+
+    personal_settings->waypoints.data = (ambit_waypoint_t*)malloc(sizeof(ambit_waypoint_t)*ambit_pack_count);
+    personal_settings->waypoints.count = ambit_pack_count;
+
+    for(int x=0;x<ambit_pack_count;x++) {
+        personal_settings->waypoints.data[x].altitude = 0;
+        personal_settings->waypoints.data[x].index = le16toh(pack_data[x].index);
+        strncpy(personal_settings->waypoints.data[x].name, pack_data[x].name, 15);
+        strncpy(personal_settings->waypoints.data[x].route_name, pack_data[x].route_name, 15);
+        personal_settings->waypoints.data[x].ctime_second = pack_data[x].ctime_second;
+        personal_settings->waypoints.data[x].ctime_minute = pack_data[x].ctime_minute;
+        personal_settings->waypoints.data[x].ctime_hour = pack_data[x].ctime_hour;
+        personal_settings->waypoints.data[x].ctime_day = pack_data[x].ctime_day;
+        personal_settings->waypoints.data[x].ctime_month = pack_data[x].ctime_month;
+        personal_settings->waypoints.data[x].ctime_year = le16toh(pack_data[x].ctime_year);
+        personal_settings->waypoints.data[x].latitude = le32toh(pack_data[x].latitude);
+        personal_settings->waypoints.data[x].longitude = le32toh(pack_data[x].longitude);
+        personal_settings->waypoints.data[x].type = pack_data[x].type;
+        personal_settings->waypoints.data[x].status = pack_data[x].status;
+    }
+
+    if(pack_data != NULL) {
+        free(pack_data);
+    }
+
+    return ret;
+}
+
+int ambit_navigation_write(ambit_object_t *object, ambit_personal_settings_t *personal_settings) {
+
+    int ret = -1;
+
+    if(personal_settings->waypoints.count>0) {
+        ambit_pack_waypoint_t *pack_data;
+        pack_data = (ambit_pack_waypoint_t*)calloc(personal_settings->waypoints.count,sizeof(ambit_pack_waypoint_t));
+
+        for(int x=0; x<personal_settings->waypoints.count; x++) {
+            //pack_data[x].index = le16toh(pack_data[x].index);
+            pack_data[x].index = 0;
+            strncpy(pack_data[x].name, personal_settings->waypoints.data[x].name, 15);
+            strncpy(pack_data[x].route_name, personal_settings->waypoints.data[x].route_name, 15);
+            pack_data[x].ctime_second = personal_settings->waypoints.data[x].ctime_second;
+            pack_data[x].ctime_minute = personal_settings->waypoints.data[x].ctime_minute;
+            pack_data[x].ctime_hour = personal_settings->waypoints.data[x].ctime_hour;
+            pack_data[x].ctime_day = personal_settings->waypoints.data[x].ctime_day;
+            pack_data[x].ctime_month = personal_settings->waypoints.data[x].ctime_month;
+            pack_data[x].ctime_year = htole16(personal_settings->waypoints.data[x].ctime_year);
+            pack_data[x].latitude = htole32(personal_settings->waypoints.data[x].latitude);
+            pack_data[x].longitude = htole32(personal_settings->waypoints.data[x].longitude);
+            pack_data[x].type = personal_settings->waypoints.data[x].type;
+            pack_data[x].status = personal_settings->waypoints.data[x].status;
+        }
+
+        ret = ambit_navigation_waypoint_write(object, pack_data, personal_settings->waypoints.count);
+        free(pack_data);
+
+        if(ret > -1 && personal_settings->routes.count>0) {
+            ret = ambit_navigation_route_write(object, personal_settings);
+        }
+    } else {
+        ret = ambit_navigation_waypoint_write(object, NULL, 0);
+    }
+
+    return ret;
+}
+
+int ambit_navigation_waypoint_read(ambit_object_t *object, ambit_pack_waypoint_t **waypoint_data, uint16_t *way_point_count) {
+
+    uint8_t *reply_data = NULL;
+    size_t replylen = 0;
+    ambit_pack_waypoint_t *send_waypoint_data = NULL;
+    ambit_pack_waypoint_t *waypoint_return_list = NULL;
+    uint8_t *send_data = NULL;
+    size_t sendlen = 0;
+    uint16_t x;
+
+    *way_point_count = 0;
+
+    //get number of waypoints
+    if( libambit_protocol_command(object, ambit_command_waypoint_count, NULL, 0, &reply_data, &replylen, 0) != 0) {
+        LOG_WARNING("Failed to read number of waypoints entries");
+        libambit_protocol_free(reply_data);
+        reply_data = NULL;
+        return -1;
+    }
+
+    *way_point_count = le16toh(*(uint16_t*)(reply_data));
+    waypoint_return_list = malloc(sizeof(ambit_pack_waypoint_t)*(*way_point_count));
+
+    libambit_protocol_free(reply_data);
+    reply_data = NULL;
+
+    sendlen = sizeof(ambit_pack_waypoint_t);
+
+    for(x=0; x<(*way_point_count); ++x) {
+
+        send_waypoint_data = malloc(sizeof(ambit_pack_waypoint_t));
+        send_data = malloc(sizeof(ambit_pack_waypoint_t));
+
+        send_waypoint_data->index = htole16(x);
+
+        memcpy(send_data, send_waypoint_data, sizeof(ambit_pack_waypoint_t));
+        free(send_waypoint_data);
+
+        if( libambit_protocol_command(object, ambit_command_waypoint_read, send_data, sendlen, &reply_data ,&replylen , 0) == 0 ) {
+            memcpy(&waypoint_return_list[x], reply_data, sizeof(ambit_pack_waypoint_t));
+
+#ifdef DEBUG_PRINT_INFO
+            ambit_navigation_print_struct(&waypoint_return_list[x]);
+            printf("\n");
+#endif
+
+            if(waypoint_return_list[x].type < NUM_WAYPOINTS_AMBIT) {
+                waypoint_return_list[x].type = ambit_waypoint_types_to_movescount[waypoint_return_list[x].type];
+            } else {
+                waypoint_return_list[x].type = movescount_waypoint_type_poi;
+            }
+
+        } else {
+            LOG_WARNING("ambit_command_waypoint_read failed: %u\n", x);
+        }
+
+        if(send_data != NULL) {
+            free(send_data);
+            send_data = NULL;
+        }
+        libambit_protocol_free(reply_data);
+        reply_data = NULL;
+
+    }
+
+    *waypoint_data = waypoint_return_list;
+
+    return 0;
+}
+
+int ambit_navigation_waypoint_write(ambit_object_t *object,ambit_pack_waypoint_t *waypoint_data, uint16_t waypoint_count) {
+
+    //Notify device, start write
+    if( libambit_protocol_command(object, ambit_command_write_start, NULL, 0, NULL, NULL, 0) != 0) {
+        LOG_WARNING("Device denied writing (navigation)");
+        return -1;
+    }
+
+    //Remove all device navigation elements before write
+    if( libambit_protocol_command(object, ambit_command_nav_memory_delete, NULL, 0, NULL, NULL, 0) != 0) {
+        LOG_WARNING("Failed to remove navigation points from memory");
+        return -1;
+    }
+
+    if(waypoint_count>0 && waypoint_data != NULL) {
+        uint8_t *send_data = NULL;
+        ambit_pack_waypoint_t send_pack;
+        send_data = malloc(sizeof(ambit_pack_waypoint_t));
+
+        for(int x=0; x < waypoint_count; x++) {
+            waypoint_data[x].index = x;
+            waypoint_data[x].index = 0;
+            send_pack = waypoint_data[x];
+            send_pack.type = ambit_waypoint_types_from_movescount[send_pack.type];
+            send_pack.status = 0;
+            memcpy(send_data, &send_pack, sizeof(ambit_pack_waypoint_t));
+            libambit_protocol_command(object, ambit_command_waypoint_write, send_data, sizeof(ambit_pack_waypoint_t), NULL, NULL, 0);
+        }
+
+        free(send_data);
+    }
+
+    return 0;
+}
+
+#ifdef DEBUG_PRINT_INFO
+void ambit_navigation_print_struct(ambit_pack_waypoint_t *str) {
+
+	printf("index: %u\n", le16toh(str->index));
+	printf("unknown: %u\n", str->unknown);
+	printf("name: %s\n", str->name);
+	printf("route_name: %s\n", str->route_name);
+	printf("ctime_second: %u\n", str->ctime_second);
+	printf("ctime_minute: %u\n", str->ctime_minute);
+	printf("ctime_hour: %u\n", str->ctime_hour);
+	printf("ctime_day: %u\n", str->ctime_day);
+	printf("ctime_month: %u\n", str->ctime_month);
+	printf("ctime_year: %u\n", le16toh(str->ctime_year));
+	printf("latitude: %i\n", le16toh(str->latitude));
+	printf("longitude: %i\n", le16toh(str->longitude));
+	printf("type: %u\n", le16toh(str->type));
+	printf("unknown2: %u\n", str->unknown2);
+	printf("name_count: %u\n", str->name_count);
+	printf("status: %u\n", str->status);
+
+}
+#endif
+
+ambit_pack_routes_t ambit_navigation_route_init(uint16_t route_count, uint32_t routepoints_count) {
+    ambit_pack_routes_t routes;
+    routes.data_head = (ambit_pack_route_info_head_t*)calloc(1, sizeof(ambit_pack_route_info_head_t));
+    routes.data_head->unknown1 = htole16(12296);
+    routes.data_head->unknown3 = 1;
+    routes.data_head->route_count = htole16(route_count);
+    routes.data_head->routepoint_count = htole32(routepoints_count);
+    routes.data_route_info = (ambit_pack_route_info_t*)calloc(route_count, sizeof(ambit_pack_route_info_t));
+    routes.data_routepoints = (ambit_pack_routepoints_t*)calloc(routepoints_count, sizeof(ambit_pack_routepoints_t));
+    routes.route_info_length = sizeof(ambit_pack_route_info_head_t)+sizeof(ambit_pack_route_info_t)*route_count;
+    routes.route_info_offset = 0;
+    routes.routepoints_length = sizeof(ambit_pack_routepoints_t)*routepoints_count;
+    routes.routepoints_offset = 0;
+    return routes;
+}
+void ambit_navigation_route_free(ambit_pack_routes_t routes) {
+    if(routes.data_head != NULL) {
+        free(routes.data_head);
+    }
+    if(routes.data_route_info != NULL) {
+        free(routes.data_route_info);
+    }
+    if(routes.data_routepoints!= NULL) {
+        free(routes.data_routepoints);
+    }
+}
+
+void debug_print_hex(uint8_t *data, size_t datalen) {
+    printf("Data:");
+
+    for(int x=0; x<datalen; ++x) {
+        if(x%2==0) printf(" ");
+        printf("%02x", data[x]);
+    }
+
+    printf("\n");
+}
+
+int ambit_navigation_route_write(ambit_object_t *object, ambit_personal_settings_t *ps) {
+    //TODO: Split function in smaller functions
+
+    uint32_t routepoints_count_tot = 0, routepoint_start_index_offset=0, current_point_offset = 0;
+
+
+    //calculate total number of routepoints
+    for(int x=0; x<ps->routes.count;++x) {
+        routepoints_count_tot += ps->routes.data[x].points_count;
+    }
+    
+    ambit_pack_routes_t routes = ambit_navigation_route_init(ps->routes.count, routepoints_count_tot);
+
+    for(int x=0;x<ps->routes.count;++x) {
+        ambit_pack_route_info_t *cur = &(routes.data_route_info[x]);
+        ambit_route_t *cur_ps = &(ps->routes.data[x]);
+
+        strncpy(cur->name, cur_ps->name, 15);
+
+        cur->routepoint_start_index = htole32(routepoints_count_tot-cur_ps->points_count-routepoint_start_index_offset);
+        cur->routepoint_count = htole16(cur_ps->points_count);
+        cur->distance = htole32(cur_ps->distance);
+        cur->latitude = htole32(cur_ps->mid_lat);
+        cur->longitude = htole32(cur_ps->mid_lon);
+        cur->max_x_axis_rel_eastern_point = 0; //Will be set later
+        cur->max_y_axis_rel_nothern_point = 0; //Will be set later
+        cur->unknown1 = 0xffff; //probably needs fix
+        cur->unknown2 = 0xffff; //probably needs fix
+        cur->unknown3 = 0;
+
+        routepoint_start_index_offset += cur->routepoint_count;
+
+        //pack routepoints
+        current_point_offset = cur->routepoint_start_index;
+
+
+        for(int y=0;y<cur_ps->points_count;++y) {
+            int32_t rel_x = (int32_t)(distance_calc((double)(cur_ps->mid_lat)/10000000, (double)(cur_ps->mid_lon)/10000000, (double)(cur_ps->mid_lat)/10000000, (double)(cur_ps->points[y].lon)/10000000)*1000);
+
+            if(cur_ps->points[y].lon<cur_ps->mid_lon) {
+                rel_x *= -1;
+            }
+
+            int32_t rel_y = (int32_t)(distance_calc((double)(cur_ps->mid_lat)/10000000, (double)(cur_ps->mid_lon)/10000000, (double)(cur_ps->points[y].lat)/10000000, (double)(cur_ps->mid_lon)/10000000)*1000);
+
+            if(cur_ps->points[y].lat<cur_ps->mid_lat) {
+                rel_y *= -1;
+            }
+
+            if(rel_x > cur->max_x_axis_rel_eastern_point) {
+                cur->max_x_axis_rel_eastern_point = htole32(rel_x);
+            }
+            if(rel_y > cur->max_y_axis_rel_nothern_point) {
+                cur->max_y_axis_rel_nothern_point = htole32(rel_y);
+            }
+
+            //printf("x_axis_rel: %imeters (%i)\n", rel_x, cur_ps->points[y].lon);
+            //printf("y_axis_rel: %imeters (%i)\n", rel_y, cur_ps->points[y].lat);
+
+            routes.data_routepoints[current_point_offset].x_axis_rel = htole32(rel_x);
+            routes.data_routepoints[current_point_offset].y_axis_rel = htole32(rel_y);
+            ++current_point_offset;
+        }
+    }
+
+    ambit_navigation_route_add_checksum(&routes);
+    ambit_navigation_route_write_to_packs(object, &routes);
+
+    ambit_navigation_route_free(routes);
+    return 0;
+}
+
+int ambit_navigation_route_write_to_packs(ambit_object_t *object, ambit_pack_routes_t *routes) {
+
+    int ret = 0;
+    size_t max_pack_len = 1024;
+    size_t pack_len = 0;
+    uint16_t pack_sequence = 0;
+    uint8_t *data;
+    uint32_t device_memory_addr = 0x041EB0;
+    ambit_pack_write_head_t write_head;
+
+    //first info pack
+    size_t writelen = fmin(max_pack_len, (routes->route_info_length));
+    pack_len = sizeof(ambit_pack_write_head_t)+writelen;
+    write_head.memory_addr_start = htole32(device_memory_addr);
+    write_head.pack_len = htole16(writelen);
+    write_head.pack_sequence = 0;
+
+    data = (uint8_t*)malloc(pack_len);
+    memcpy(data, &write_head, sizeof(ambit_pack_write_head_t));
+    memcpy(data+sizeof(ambit_pack_write_head_t),
+            routes->data_head,
+            sizeof(ambit_pack_route_info_head_t));
+    memcpy(data+sizeof(ambit_pack_write_head_t)+sizeof(ambit_pack_route_info_head_t),
+            routes->data_route_info,
+            writelen-sizeof(ambit_pack_route_info_head_t));
+
+
+    //Write to device;
+    //debug_print_hex(data, pack_len);
+    ret = libambit_protocol_command(object, ambit_command_data_write, data, pack_len, NULL, NULL, 0);
+    routes->route_info_offset += writelen;
+
+    free(data);
+
+    if(ret == -1) {
+        return ret;
+    }
+
+    while(routes->route_info_offset < routes->route_info_length) {
+        device_memory_addr += max_pack_len;
+        ++pack_sequence;
+        writelen = fmin(max_pack_len, routes->route_info_length-routes->route_info_offset);
+        pack_len = sizeof(ambit_pack_write_head_t)+writelen;
+        write_head.memory_addr_start = htole32(device_memory_addr);
+        write_head.pack_len = htole16(writelen);
+        //write_head.pack_sequence = htole16(pack_sequence);
+        write_head.pack_sequence = 0;
+
+        data = (uint8_t*)malloc(sizeof(ambit_pack_write_head_t)+writelen);
+
+        memcpy(data, &write_head, sizeof(ambit_pack_write_head_t));
+        memcpy(data+sizeof(ambit_pack_write_head_t),
+            (uint8_t*)(routes->data_route_info) + (routes->route_info_offset - sizeof(ambit_pack_route_info_head_t)),
+            writelen);
+
+
+        //Write to device
+        //debug_print_hex(data, pack_len);
+        ret = libambit_protocol_command(object, ambit_command_data_write, data, pack_len, NULL, NULL, 0);
+        routes->route_info_offset += writelen;
+        free(data);
+
+        if(ret == -1) {
+            return ret;
+        }
+    }
+
+    //Write route points
+    device_memory_addr = 0x042830;
+
+    while(routes->routepoints_offset < routes->routepoints_length) {
+        writelen = fmin(max_pack_len, routes->routepoints_length-routes->routepoints_offset);
+        write_head.memory_addr_start = htole32(device_memory_addr);
+        write_head.pack_len = htole16(writelen);
+        data = (uint8_t*)malloc(sizeof(ambit_pack_write_head_t)+writelen);
+
+        memcpy(data, &write_head, sizeof(ambit_pack_write_head_t));
+        memcpy(data+sizeof(ambit_pack_write_head_t),
+                (uint8_t*)(routes->data_routepoints) + routes->routepoints_offset,
+                writelen);
+        pack_len = sizeof(ambit_pack_write_head_t)+writelen;
+ 
+        //Write to device
+        //debug_print_hex(data, pack_len);
+        ret = libambit_protocol_command(object, ambit_command_data_write, data, pack_len, NULL, NULL, 0);
+        routes->routepoints_offset += writelen;
+        free(data);
+        device_memory_addr += max_pack_len;
+    }
+
+
+    //Data tail len
+
+    device_memory_addr = 0x041eb0;
+    write_head.memory_addr_start = htole32(device_memory_addr);
+    write_head.pack_len = htole16(writelen);
+    pack_len = sizeof(ambit_pack_write_head_t);
+
+    //Write to device
+    //debug_print_hex((uint8_t*)&write_head, pack_len);
+    ret = libambit_protocol_command(object, ambit_command_data_tail_len, (uint8_t*)&write_head, pack_len, NULL, NULL, 0);
+    return 0;
+
+}
+
+void ambit_navigation_route_add_checksum(ambit_pack_routes_t *routes)
+{
+    uint8_t *data;
+    size_t datalen_info_packs = sizeof(ambit_pack_route_info_t)*
+                                routes->data_head->route_count;
+    size_t datalen_point_packs = sizeof(ambit_pack_routepoints_t)*
+                                routes->data_head->routepoint_count;
+
+    size_t datalen = datalen_info_packs + datalen_point_packs;
+    data = (uint8_t*)malloc(datalen);
+
+    for(int x=0; x<routes->data_head->route_count;++x) {
+
+        memcpy(data+(sizeof(ambit_pack_route_info_t)*x),
+                &(routes->data_route_info[x]),
+                sizeof(ambit_pack_route_info_t));
+    }
+
+
+    memcpy(data+datalen_info_packs,
+            routes->data_routepoints,
+            datalen_point_packs);
+
+    routes->data_head->checksum = crc16_ccitt_false(data, datalen);
+    free(data);
+}
diff --git a/src/libambit/device_driver_ambit_navigation.h b/src/libambit/device_driver_ambit_navigation.h
new file mode 100644
index 0000000..3a67d73
--- /dev/null
+++ b/src/libambit/device_driver_ambit_navigation.h
@@ -0,0 +1,140 @@
+/*
+ * (C) Copyright 2017 Lars Andre Landås
+ *
+ * This file is part of libambit.
+ *
+ * libambit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Contributors:
+ * Lars Andre Landås (landas at gmail.com)
+ * Kristoffer Tonheim (kristoffer.tonheim at gmail.com)
+ *
+ */
+
+#ifndef __DEVICE_DRIVER_AMBIT_NAVIGATION_H__
+#define __DEVICE_DRIVER_AMBIT_NAVIGATION_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libambit.h"
+#include "distance.h"
+#include "crc16.h"
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+// Altitude is not stored inside Ambit2 S
+
+typedef struct __attribute__((__packed__)) ambit_pack_waypoint_s {
+    uint16_t      index;
+    uint16_t      unknown;
+    char          name[16];
+    char          route_name[16];
+    uint8_t       ctime_second;
+    uint8_t       ctime_minute;
+    uint8_t       ctime_hour;
+    uint8_t       ctime_day;
+    uint8_t       ctime_month;
+    uint16_t      ctime_year;
+    int32_t       latitude;
+    int32_t       longitude;
+    uint8_t       type;
+    uint8_t       unknown2;
+    uint8_t       name_count;
+    uint8_t       status; //0 - synced, 1 - (added in watch), 2 - (removed in watch)
+} ambit_pack_waypoint_t;
+
+typedef struct __attribute__((__packed__)) ambit_pack_write_head_s {
+    uint32_t      memory_addr_start; // +1024
+    uint16_t      pack_len; //bytes
+    uint16_t      pack_sequence;
+} ambit_pack_write_head_t;
+
+typedef struct __attribute__((__packed__)) ambit_pack_route_info_head_s {
+    uint16_t      unknown1; //always 12296 (can be two uint8_t?)
+    uint8_t       unknown2; //always 0?
+    uint8_t       unknown3; //always 1?
+    uint16_t      route_count;
+    uint16_t      unknown4; //always 0?
+    uint32_t      routepoint_count;
+    uint16_t      checksum;
+    uint16_t      unknown6; //always 0
+    uint16_t      unknown8; //always 0
+    uint16_t      unknown9; //always 0
+    uint16_t      unknown10; //always 0
+    uint16_t      unknown11; //always 0
+    uint16_t      unknown12; //always 0
+    uint16_t      unknown13; //always 0
+    uint16_t      unknown14; //always 0
+    uint16_t      unknown15; //always 0
+} ambit_pack_route_info_head_t;
+
+typedef struct __attribute__((__packed__)) ambit_pack_route_info_s {
+    char          name[16];
+    uint32_t      routepoint_start_index;
+    uint16_t      routepoint_count;
+    uint32_t      distance; //length of route from first to last point in meters
+    int32_t       latitude;
+    int32_t       longitude;
+    int32_t       max_x_axis_rel_eastern_point; //why??
+    int32_t       max_y_axis_rel_nothern_point; //Why??
+    uint16_t      unknown1; //Mostly 0xffff
+    uint16_t      unknown2; //Mostly 0xffff
+    uint16_t      unknown3; //Always 0??
+} ambit_pack_route_info_t;
+
+typedef struct __attribute__((__packed__)) ambit_pack_routepoints_s {
+    int32_t       x_axis_rel;
+    int32_t       y_axis_rel;
+} ambit_pack_routepoints_t;
+
+typedef struct ambit_pack_routes_s {
+    ambit_pack_route_info_head_t    *data_head;
+    ambit_pack_route_info_t         *data_route_info;
+    ambit_pack_routepoints_t        *data_routepoints;
+
+    size_t route_info_length; //bytes
+    size_t route_info_offset; //bytes
+    size_t routepoints_length; //bytes
+    size_t routepoints_offset; //bytes
+} ambit_pack_routes_t;
+
+// Cross reference table for converting to and from movescount waypoint type id
+#define NUM_WAYPOINTS_MOVESCOUNT 34
+#define NUM_WAYPOINTS_AMBIT 18
+
+const uint8_t ambit_waypoint_types_from_movescount[NUM_WAYPOINTS_MOVESCOUNT];
+const uint8_t ambit_waypoint_types_to_movescount[NUM_WAYPOINTS_AMBIT];
+
+int ambit_navigation_read(ambit_object_t *object, ambit_personal_settings_t *settings);
+int ambit_navigation_write(ambit_object_t *object, ambit_personal_settings_t *settings);
+int ambit_navigation_waypoint_read(ambit_object_t *object, ambit_pack_waypoint_t **waypoint_data, uint16_t *waypoint_count);
+int ambit_navigation_waypoint_write(ambit_object_t *object,ambit_pack_waypoint_t *waypoint_data, uint16_t waypoint_count);
+void ambit_navigation_print_struct(ambit_pack_waypoint_t *str);
+
+ambit_pack_routes_t ambit_navigation_route_init(uint16_t route_count, uint32_t routepoints_count);
+void ambit_navigation_route_free(ambit_pack_routes_t routes);
+
+int ambit_navigation_route_write(ambit_object_t *object, ambit_personal_settings_t *ps);
+int ambit_navigation_route_write_to_packs(ambit_object_t *object, ambit_pack_routes_t *routes);
+void ambit_navigation_route_add_checksum(ambit_pack_routes_t *routes);
+
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+
+#endif /* __DEVICE_DRIVER_AMBIT_NAVIGATION_H__ */
diff --git a/src/libambit/distance.c b/src/libambit/distance.c
new file mode 100644
index 0000000..85dfdb0
--- /dev/null
+++ b/src/libambit/distance.c
@@ -0,0 +1,58 @@
+/*
+ * (C) Copyright 2017 Lars Andre Landås
+ *
+ * This file is part of libambit.
+ *
+ * libambit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Contributors:
+ *
+ */
+
+
+#include "distance.h"
+
+#define EARTH_RADIUS 6367
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+double deg2rad(double deg)
+{
+    return deg * 4.0 * atan(1.0) / 180.0;
+}
+
+double distance_calc(double lat_a, double long_a, double lat_b, double long_b)
+{
+    //return distance in km
+    lat_a = deg2rad(lat_a);
+    lat_b = deg2rad(lat_b);
+    long_a = deg2rad(long_a);
+    long_b = deg2rad(long_b);
+
+    double lat_dist = lat_b - lat_a;
+    double long_dist = long_b - long_a;
+
+    double tmp = pow(sin(lat_dist/2),2) +
+        cos(lat_a) * cos(lat_b) * pow(sin(long_dist/2),2);
+    tmp = 2 * atan2(sqrt(tmp), sqrt(1-tmp));
+    tmp = (EARTH_RADIUS * tmp);
+    return tmp;
+}
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
diff --git a/src/libambit/distance.h b/src/libambit/distance.h
new file mode 100644
index 0000000..e971824
--- /dev/null
+++ b/src/libambit/distance.h
@@ -0,0 +1,44 @@
+/*
+ * (C) Copyright 2017 Lars Andre Landås
+ *
+ * This file is part of libambit.
+ *
+ * libambit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Contributors:
+ *
+ */
+
+#ifndef __DISTANCE_H__
+#define __DISTANCE_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include <math.h>
+#include "libambit.h"
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+double deg2rad(double deg);
+double distance_calc(double lat_a, double long_a, double lat_b, double long_b);
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+
+#endif /* __DISTANCE_H__ */
+
diff --git a/src/libambit/libambit.c b/src/libambit/libambit.c
index 78ffc8c..1cadcb2 100644
--- a/src/libambit/libambit.c
+++ b/src/libambit/libambit.c
@@ -272,6 +272,34 @@ int libambit_gps_orbit_write(ambit_object_t *object, uint8_t *data, size_t datal
     return ret;
 }
 
+int libambit_sport_mode_write(ambit_object_t *object, ambit_sport_mode_device_settings_t *ambit_sport_modes)
+{
+    int ret = -1;
+
+    if (object->driver != NULL && object->driver->sport_mode_write != NULL) {
+        ret = object->driver->sport_mode_write(object, ambit_sport_modes);
+    }
+    else {
+        LOG_WARNING("Driver does not support sport_mode_write");
+    }
+
+    return ret;
+}
+
+int libambit_app_data_write(ambit_object_t *object, ambit_sport_mode_device_settings_t *ambit_sport_modes, ambit_app_rules_t* ambit_apps)
+{
+    int ret = -1;
+
+    if (object->driver != NULL && object->driver->app_data_write != NULL) {
+        ret = object->driver->app_data_write(object, ambit_sport_modes, ambit_apps);
+    }
+    else {
+        LOG_WARNING("Driver does not support app_data_write");
+    }
+
+    return ret;
+}
+
 int libambit_log_read(ambit_object_t *object, ambit_log_skip_cb skip_cb, ambit_log_push_cb push_cb, ambit_log_progress_cb progress_cb, void *userref)
 {
     int ret = -1;
@@ -318,6 +346,200 @@ void libambit_log_entry_free(ambit_log_entry_t *log_entry)
     }
 }
 
+void libambit_sport_mode_device_settings_free(ambit_sport_mode_device_settings_t *settings)
+{
+    int i;
+
+    if (settings->sport_modes != NULL) {
+        for (i=0; i<settings->sport_modes_count; i++) {
+            if (settings->sport_modes[i].display != NULL) {
+                if (settings->sport_modes[i].display->view != NULL) {
+                    free(settings->sport_modes[i].display->view);
+                }
+                free(settings->sport_modes[i].display);
+            }
+            if (settings->sport_modes[i].apps_list != NULL) {
+                free(settings->sport_modes[i].apps_list);
+            }
+        }
+        free(settings->sport_modes);
+    }
+
+    if (settings->sport_mode_groups != NULL) {
+        for (i=0; i<settings->sport_mode_groups_count; i++) {
+            if (settings->sport_mode_groups[i].sport_mode_index != NULL) {
+                free(settings->sport_mode_groups[i].sport_mode_index);
+            }
+        }
+        free(settings->sport_mode_groups);
+    }
+}
+
+ambit_sport_mode_device_settings_t *libambit_malloc_sport_mode_device_settings(void)
+{
+    ambit_sport_mode_device_settings_t *ambit_device_settings = (ambit_sport_mode_device_settings_t *)malloc(sizeof(ambit_sport_mode_device_settings_t));
+    ambit_device_settings->sport_modes = NULL;
+    ambit_device_settings->sport_modes_count = 0;
+    ambit_device_settings->sport_mode_groups = NULL;
+    ambit_device_settings->sport_mode_groups_count = 0;
+    ambit_device_settings->app_ids_count = 0;
+
+    return ambit_device_settings;
+}
+
+bool libambit_malloc_sport_modes(uint16_t count, ambit_sport_mode_device_settings_t *ambit_settings)
+{
+    ambit_sport_mode_t *ambit_sport_modes = (ambit_sport_mode_t *)malloc(sizeof(ambit_sport_mode_t) * count);
+    if (ambit_sport_modes != NULL) {
+        ambit_settings->sport_modes = ambit_sport_modes;
+        ambit_settings->sport_modes_count = count;
+
+        int i;
+        for (i=0; i<count; i++) {
+            ambit_settings->sport_modes[i].display = NULL;
+            ambit_settings->sport_modes[i].displays_count = 0;
+            ambit_settings->sport_modes[i].apps_list = NULL;
+            ambit_settings->sport_modes[i].apps_list_count = 0;
+        }
+    }
+    else {
+        ambit_settings->sport_modes = NULL;
+        ambit_settings->sport_modes_count = 0;
+    }
+
+    return ambit_sport_modes != NULL;
+}
+
+bool libambit_malloc_sport_mode_groups(uint16_t count, ambit_sport_mode_device_settings_t *ambit_settings)
+{
+    ambit_sport_mode_group_t *ambit_sport_mode_groups = (ambit_sport_mode_group_t *)malloc(sizeof(ambit_sport_mode_group_t) * count);
+    if (ambit_sport_mode_groups != NULL) {
+        ambit_settings->sport_mode_groups = ambit_sport_mode_groups;
+        ambit_settings->sport_mode_groups_count = count;
+
+        int i;
+        for (i=0; i<count; i++) {
+            ambit_settings->sport_mode_groups[i].sport_mode_index = NULL;
+            ambit_settings->sport_mode_groups[i].sport_mode_index_count = 0;
+        }
+    }
+    else {
+        ambit_settings->sport_mode_groups = NULL;
+        ambit_settings->sport_mode_groups_count = 0;
+    }
+
+    return ambit_sport_mode_groups != NULL;
+}
+
+bool libambit_malloc_sport_mode_app_ids(uint16_t count, ambit_sport_mode_t *ambit_sport_mode)
+{
+    ambit_apps_list_t *ambit_app_ids = (ambit_apps_list_t *)malloc(sizeof(ambit_apps_list_t) * count);
+    if (ambit_app_ids != NULL) {
+        ambit_sport_mode->apps_list = ambit_app_ids;
+        ambit_sport_mode->apps_list_count = count;
+    }
+    else {
+        ambit_sport_mode->apps_list = NULL;
+        ambit_sport_mode->apps_list_count = 0;
+    }
+    return ambit_app_ids != NULL;
+}
+
+bool libambit_malloc_sport_mode_displays(uint16_t count, ambit_sport_mode_t *ambit_sport_mode)
+{
+    ambit_sport_mode_display_t *ambit_displays = (ambit_sport_mode_display_t *)malloc(sizeof(ambit_sport_mode_display_t) * count);
+    if (ambit_displays != NULL) {
+        ambit_sport_mode->display = ambit_displays;
+        ambit_sport_mode->displays_count = count;
+
+        int i;
+        for (i=0; i<count; i++) {
+            ambit_sport_mode->display[i].view = NULL;
+            ambit_sport_mode->display[i].views_count = 0;
+        }
+    }
+    else {
+        ambit_sport_mode->display = NULL;
+        ambit_sport_mode->displays_count = 0;
+    }
+    return ambit_displays != NULL;
+}
+
+bool libambit_malloc_sport_mode_view(uint16_t count, ambit_sport_mode_display_t *ambit_displays)
+{
+    uint16_t *ambit_views = (uint16_t *)malloc(sizeof(uint16_t) * count);
+    if (ambit_views != NULL) {
+        ambit_displays->view = ambit_views;
+        ambit_displays->views_count = count;
+    }
+    else {
+        ambit_displays->view = NULL;
+        ambit_displays->views_count = 0;
+    }
+
+    return ambit_views != NULL;
+}
+
+bool libambit_malloc_sport_mode_index(uint16_t count, ambit_sport_mode_group_t *ambit_sport_mode_group)
+{
+    uint16_t *ambit_sport_mode_index = (uint16_t *)malloc(sizeof(uint16_t) * count);
+    if (ambit_sport_mode_index != NULL) {
+        ambit_sport_mode_group->sport_mode_index = ambit_sport_mode_index;
+        ambit_sport_mode_group->sport_mode_index_count = count;
+    }
+    else
+    {
+        ambit_sport_mode_group->sport_mode_index = NULL;
+        ambit_sport_mode_group->sport_mode_index_count = 0;
+    }
+
+    return ambit_sport_mode_index != NULL;
+}
+
+void libambit_app_rules_free(ambit_app_rules_t *app_rules)
+{
+    int i;
+
+    if (app_rules->app_rules != NULL) {
+        for (i=0; i<app_rules->app_rules_count; i++) {
+            free(app_rules->app_rules[i].app_rule_data);
+        }
+        free(app_rules->app_rules);
+    }
+    free(app_rules);
+}
+
+ambit_app_rules_t *liblibambit_malloc_app_rules(void)
+{
+    ambit_app_rules_t *ambit_app_rules = (ambit_app_rules_t *)malloc(sizeof(ambit_app_rules_t));
+    ambit_app_rules->app_rules = NULL;
+    ambit_app_rules->app_rules_count = 0;
+
+    return ambit_app_rules;
+}
+
+bool libambit_malloc_app_rule(uint16_t count, ambit_app_rules_t *ambit_app_rules)
+{
+    ambit_app_rule_t *ambit_app_rule = (ambit_app_rule_t *)malloc(sizeof(ambit_app_rule_t) * count);
+    if (ambit_app_rule != NULL) {
+        ambit_app_rules->app_rules = ambit_app_rule;
+        ambit_app_rules->app_rules_count = count;
+
+        int i;
+        for (i=0; i<count; i++) {
+            ambit_app_rules->app_rules[i].app_rule_data = NULL;
+            ambit_app_rules->app_rules[i].app_rule_data_length = 0;
+            ambit_app_rules->app_rules[i].app_id = 0;
+        }
+    }
+    else {
+        ambit_app_rules->app_rules = NULL;
+        ambit_app_rules->app_rules_count = 0;
+    }
+
+    return ambit_app_rule != NULL;
+}
+
 static int device_info_get(ambit_object_t *object, ambit_device_info_t *info)
 {
     uint8_t *reply_data = NULL;
@@ -509,3 +731,93 @@ static ambit_device_info_t * ambit_device_info_new(const struct hid_device_info
 
     return device;
 }
+
+ambit_personal_settings_t* libambit_personal_settings_alloc() {
+    ambit_personal_settings_t *ps;
+    ps = (ambit_personal_settings_t*)calloc(1, sizeof(ambit_personal_settings_t));
+    ps->routes.data = NULL;
+    ps->waypoints.data = NULL;
+    return ps;
+}
+
+void libambit_personal_settings_free(ambit_personal_settings_t *personal_settings) {
+    if(personal_settings->waypoints.data != NULL) {
+        free(personal_settings->waypoints.data);
+    }
+
+    if(personal_settings->routes.data != NULL) {
+        libambit_route_free(personal_settings->routes.data, personal_settings->routes.count);
+    }
+
+    free(personal_settings);
+}
+
+ambit_route_t* libambit_route_alloc(uint16_t route_count) {
+    ambit_route_t *routes;
+    routes = (ambit_route_t*)calloc(route_count, sizeof(ambit_route_t));
+    for(int x=0; x<route_count; ++x) {
+        routes[x].points = NULL;
+    }
+    return routes;
+}
+
+void libambit_route_free(ambit_route_t *routes, uint16_t route_count) {
+
+    if(route_count!=0) {
+        for(int x=0; x<route_count; ++x) {
+            if(routes[x].points != NULL) {
+                free(routes[x].points);
+            }
+        }
+    } else if(routes->points != NULL) {
+        free(routes->points);
+    }
+
+    free(routes);
+}
+
+void libambit_waypoint_append(ambit_personal_settings_t *ps, ambit_waypoint_t *waypoints, uint8_t num_to_append) {
+
+    if(num_to_append == 0) {
+        //Do nothing
+        return;
+    }
+
+    ambit_waypoint_t *old_array = ps->waypoints.data;
+    uint8_t old_count = ps->waypoints.count;
+
+    ps->waypoints.count += num_to_append;
+    ps->waypoints.data = (ambit_waypoint_t*)malloc(sizeof(ambit_waypoint_t)*ps->waypoints.count);
+
+    if(old_count>0) {
+        memcpy(ps->waypoints.data, old_array, sizeof(ambit_waypoint_t)*old_count);
+        if(old_array != NULL) {
+            free(old_array);
+        }
+    }
+    memcpy(&(ps->waypoints.data[old_count]), waypoints, sizeof(ambit_waypoint_t)*num_to_append);
+}
+
+int libambit_navigation_read(ambit_object_t *object, ambit_personal_settings_t *personal_settings) {
+    int ret = -1;
+
+    if (object->driver != NULL && object->driver->navigation_read != NULL) {
+        ret = object->driver->navigation_read(object, personal_settings);
+    }
+    else {
+        LOG_WARNING("Driver does not support navigation_waypoint_read");
+    }
+
+    return ret;
+}
+
+int libambit_navigation_write(ambit_object_t *object, ambit_personal_settings_t *personal_settings) {
+
+    int ret = -1;
+
+    if (object->driver != NULL && object->driver->navigation_write != NULL) {
+        ret = object->driver->navigation_write(object, personal_settings);
+    }
+    return ret;
+}
+
diff --git a/src/libambit/libambit.h b/src/libambit/libambit.h
index 264a2d2..b03ffdb 100644
--- a/src/libambit/libambit.h
+++ b/src/libambit/libambit.h
@@ -52,6 +52,52 @@ typedef struct ambit_device_status_s {
     uint8_t  charge;
 } ambit_device_status_t;
 
+typedef struct ambit_waypoint_s {
+    uint16_t      index;
+    char          name[50];
+    char          route_name[50];
+    uint8_t       ctime_second;
+    uint8_t       ctime_minute;
+    uint8_t       ctime_hour;
+    uint8_t       ctime_day;
+    uint8_t       ctime_month;
+    uint16_t      ctime_year;
+    int32_t       latitude;
+    int32_t       longitude;
+    uint16_t      altitude;
+    uint8_t       type;
+    uint8_t       status;
+} ambit_waypoint_t;
+
+typedef struct ambit_routepoint_s {
+    int32_t      lat;      //devide value by 10000000
+    int32_t      lon;      //devide value by 10000000
+    int32_t      altitude; //meters
+    uint32_t     distance; //relative distance from 0 - 1.000.000
+} ambit_routepoint_t;
+
+typedef struct ambit_route_s {
+    uint32_t      id;
+    char          name[50];
+    uint16_t      waypoint_count;
+    uint16_t      activity_id;
+    uint16_t      altitude_asc; //meters
+    uint16_t      altitude_dec; //meters
+    uint16_t      points_count;
+    uint32_t      distance;
+    int32_t       start_lat;  //devide value by 10000000
+    int32_t       start_lon;  //devide value by 10000000
+    int32_t       end_lat;  //devide value by 10000000
+    int32_t       end_lon;  //devide value by 10000000
+    int32_t       max_lat;  //devide value by 10000000
+    int32_t       min_lat;  //devide value by 10000000
+    int32_t       max_lon;  //devide value by 10000000
+    int32_t       min_lon;  //devide value by 10000000
+    int32_t       mid_lat;  //devide value by 10000000
+    int32_t       mid_lon;  //devide value by 10000000
+    ambit_routepoint_t *points;
+} ambit_route_t;
+
 typedef struct ambit_personal_settings_s {
     uint8_t  sportmode_button_lock;
     uint8_t  timemode_button_lock;
@@ -106,6 +152,14 @@ typedef struct ambit_personal_settings_s {
     uint8_t  automatic_bikepower_calib;
     uint8_t  automatic_footpod_calib;
     uint8_t  training_program;
+    struct {
+        ambit_route_t *data;
+        uint8_t  count;
+    } routes;
+    struct {
+        ambit_waypoint_t *data;
+        uint16_t count;
+    } waypoints;
 } ambit_personal_settings_t;
 
 typedef struct ambit_log_date_time_s {
@@ -175,6 +229,43 @@ typedef enum ambit_log_sample_periodic_type_e {
     ambit_log_sample_periodic_type_ruleoutput5 = 0x68
 } ambit_log_sample_periodic_type_t;
 
+typedef enum movescount_waypoint_type_e {
+    movescount_waypoint_type_building = 0,
+    movescount_waypoint_type_home = 1,
+    movescount_waypoint_type_car = 2,
+    movescount_waypoint_type_parking = 3,
+    movescount_waypoint_type_camp = 4,
+    movescount_waypoint_type_camping = 5,
+    movescount_waypoint_type_food = 6,
+    movescount_waypoint_type_restaurant = 7,
+    movescount_waypoint_type_cafe = 8,
+    movescount_waypoint_type_lodging = 9,
+    movescount_waypoint_type_hostel = 10,
+    movescount_waypoint_type_hotel = 11,
+    movescount_waypoint_type_water = 12,
+    movescount_waypoint_type_river = 13,
+    movescount_waypoint_type_lake = 14,
+    movescount_waypoint_type_coast = 15,
+    movescount_waypoint_type_mouantain = 16,
+    movescount_waypoint_type_hill = 17,
+    movescount_waypoint_type_valley = 18,
+    movescount_waypoint_type_cliff = 19,
+    movescount_waypoint_type_forest = 20,
+    movescount_waypoint_type_crossroad = 21,
+    movescount_waypoint_type_sight = 22,
+    movescount_waypoint_type_beginning = 23,
+    movescount_waypoint_type_end = 24,
+    movescount_waypoint_type_geocache = 25,
+    movescount_waypoint_type_poi = 26,
+    movescount_waypoint_type_road = 27,
+    movescount_waypoint_type_trail = 28,
+    movescount_waypoint_type_rock = 29,
+    movescount_waypoint_type_meadow = 30,
+    movescount_waypoint_type_cave = 31,
+    movescount_waypoint_type_internal_wp_start = 32,
+    movescount_waypoint_type_internal_wp_end = 33
+} movescount_waypoint_type_t;
+
 typedef struct ambit_log_sample_periodic_value_s {
     ambit_log_sample_periodic_type_t type;
     union {
@@ -302,7 +393,7 @@ typedef struct ambit_log_sample_s {
         } swimming_turn;
         struct {
             uint16_t activitytype;
-            uint32_t custommode;
+            uint32_t sportmode;
         } activity;
         uint8_t cadence_source;                 /* 0x40 = Wrist */
         struct {
@@ -373,6 +464,115 @@ typedef struct ambit_log_entry_s {
     ambit_log_sample_t *samples;
 } ambit_log_entry_t;
 
+
+typedef struct ambit_sport_mode_settings_s {
+    char     activity_name[16];
+    uint16_t activity_id;
+    uint16_t sport_mode_id;
+    uint8_t  unknown1[2];
+    uint16_t hrbelt_and_pods;       /* bit pattern representing usage of hr belt or pods */
+    uint16_t alti_baro_mode;
+    uint16_t gps_interval;
+    uint16_t recording_interval;
+    uint16_t autolap;               /* m */
+    uint16_t heartrate_max;         /* bps */
+    uint16_t heartrate_min;         /* bps */
+    uint16_t use_heartrate_limits;
+    uint8_t  unknown2[2];
+    uint16_t auto_pause;
+    uint16_t auto_scroll;           /* s */
+    uint16_t use_interval_timer;
+    uint16_t interval_repetitions;
+    uint16_t interval_timer_max_unit;   /* m or s */
+    uint8_t  unknown3[6];
+    uint16_t interval_timer_max;    /* s or m */ /*Maybe 2 bytes from unknown3 should be included in this field? */
+    uint8_t  unknown4[2];
+    uint16_t interval_timer_min_unit;   /* m or s */
+    uint8_t  unknown5[6];
+    uint16_t interval_timer_min;    /* s or m */ /*Maybe 2 bytes from unknown3 should be included in this field? */
+    uint8_t  unknown6[14];
+    uint16_t backlight_mode;
+    uint16_t display_mode;
+    uint16_t quick_navigation;
+} ambit_sport_mode_settings_t;
+
+typedef struct ambit_sport_mode_display_layout_s {
+    uint16_t header;
+    uint16_t length;
+    uint16_t display_layout;
+    uint8_t unknown[2];
+} ambit_sport_mode_display_layout_t;
+
+typedef struct ambit_sport_mode_row_s {
+    uint16_t header;
+    uint16_t length;
+    uint16_t row_nbr;
+    uint16_t item;
+} ambit_sport_mode_row_t;
+
+typedef struct ambit_sport_mode_view_s {
+    uint16_t header;
+    uint16_t length;
+    uint16_t item;
+} ambit_sport_mode_view_t;
+
+typedef struct ambit_write_header_s {
+    uint16_t header;
+    uint16_t length;
+} ambit_write_header_t;
+
+typedef struct ambit_sport_mode_display_s {
+    uint16_t requiresHRBelt;
+    uint16_t type;
+    uint16_t row1;
+    uint16_t row2;
+    uint16_t row3;
+    uint32_t views_count;
+    uint16_t *view;
+} ambit_sport_mode_display_t;
+
+typedef struct ambit_app_index_s {
+    uint16_t index;
+    uint16_t logging;
+} ambit_apps_list_t;
+
+typedef struct ambit_sport_mode_group_s {
+    uint16_t activity_id;
+    uint16_t sport_mode_group_id;
+    bool is_visible;
+    char activity_name[24];
+    uint32_t sport_mode_index_count;
+    uint16_t *sport_mode_index;
+} ambit_sport_mode_group_t;
+
+typedef struct ambit_sport_mode_s {
+    ambit_sport_mode_settings_t settings;
+    uint32_t displays_count;
+    ambit_sport_mode_display_t *display;
+    uint16_t apps_list_count;
+    ambit_apps_list_t *apps_list;
+} ambit_sport_mode_t;
+
+typedef struct ambit_sport_mode_device_settings_s {
+    uint32_t sport_modes_count;
+    ambit_sport_mode_t *sport_modes;
+    uint32_t sport_mode_groups_count;
+    ambit_sport_mode_group_t *sport_mode_groups;
+    uint32_t app_ids_count;
+    uint32_t app_ids[40];
+} ambit_sport_mode_device_settings_t;
+
+typedef struct ambit_app_rule_s {
+    uint32_t app_rule_data_length;
+    uint32_t app_id;
+    uint8_t *app_rule_data;
+} ambit_app_rule_t;
+
+typedef struct ambit_app_rules_s {
+    uint32_t app_rules_count;
+    ambit_app_rule_t *app_rules;
+} ambit_app_rules_t;
+
 /** \brief Create a list of all known Ambit clocks on the system
  *
  *  The list may include clocks that are not supported or cannot be
@@ -460,6 +660,17 @@ int libambit_gps_orbit_header_read(ambit_object_t *object, uint8_t data[8]);
 int libambit_gps_orbit_write(ambit_object_t *object, uint8_t *data, size_t datalen);
 
 /**
+ * Write Custom mode displays
+ * \param object Object to get settings from
+ * \param ambit_sport_modes settings object to be written
+ * \return 0 on success, else -1
+ */
+int libambit_sport_mode_write(ambit_object_t *object, ambit_sport_mode_device_settings_t *ambit_sport_modes);
+
+
+int libambit_app_data_write(ambit_object_t *object, ambit_sport_mode_device_settings_t *ambit_sport_modes, ambit_app_rules_t* ambit_apps);
+
+/**
  * Callback function for checking if a specific log entry should be read out or
  * skipped during log readouts
  * \param object Object reference
@@ -496,12 +707,139 @@ typedef void (*ambit_log_progress_cb)(void *userref, uint16_t log_count, uint16_
  * libambit_log_entry_free()
  */
 int libambit_log_read(ambit_object_t *object, ambit_log_skip_cb skip_cb, ambit_log_push_cb push_cb, ambit_log_progress_cb progress_cb, void *userref);
-
 /**
  * Free log entry allocated by libambit_log_read
  * \param log_entry Log entry to free
  */
 void libambit_log_entry_free(ambit_log_entry_t *log_entry);
+/**
+ * Init ambit_route_t struct
+ */
+ambit_route_t* libambit_route_alloc(uint16_t route_count);
+/**
+ * Free struct allocated by libambit_route_alloc
+ * \param personal_settings Struct to free
+ */
+void libambit_route_free(ambit_route_t *routes, uint16_t route_count);
+/**
+ * Append to a ambit_personal_settings_t.waypoints
+ */
+void libambit_waypoint_append(ambit_personal_settings_t *ps, ambit_waypoint_t *waypoints, uint8_t num_to_append);
+/**
+ * Init personal_settings struct
+ */
+ambit_personal_settings_t* libambit_personal_settings_alloc();
+/**
+ * Free struct allocated by libambit_personal_settings_alloc
+ * \param personal_settings Struct to free
+ */
+void libambit_personal_settings_free(ambit_personal_settings_t *personal_settings);
+
+/**
+ * Read Waypoint entries
+ */
+int libambit_navigation_read(ambit_object_t *object, ambit_personal_settings_t *personal_settings);
+
+/**
+ * Write Waypoint entries
+ */
+int libambit_navigation_write(ambit_object_t *object, ambit_personal_settings_t *personal_settings);
+
+/**
+ * Allocates memmory for device settings structure and
+ * initiate pointer in the structure to NULL and sport_modes_count and sport_mode_groups_count to 0.
+ * \note Caller is responsible of freeing the struct with libambit_sport_mode_device_settings_free()
+ * \return pointer to allocated data struct.
+ */
+ambit_sport_mode_device_settings_t *libambit_malloc_sport_mode_device_settings(void);
+
+/**
+ * Allocates memmory for a number of custom mode structures and
+ * initiate display pointer in the structures to NULL and displays_count to 0.
+ * \param count number of custom modes that will be allocated.
+ * \param ambit_settings structure where these custom modes belongs to.
+ * The ambit_settings will be updated to point at the allocated data and the custom modes count will be set to count.
+ * \return true if allocation was succesfull.
+ */
+bool libambit_malloc_sport_modes(uint16_t count, ambit_sport_mode_device_settings_t *ambit_settings);
+
+/**
+ * Allocates memmory for a number of custom mode group structures and
+ * initiate structure pointers to NULL and index_count to 0.
+ * \param count number of custom mode groups that will be allocated.
+ * \param ambit_settings structure where these custom mode groups belongs to.
+ * The ambit_settings will be updated to point at the allocated data and the custom mode groups count will be set to count.
+ * \return true if allocation was succesfull.
+ */
+bool libambit_malloc_sport_mode_groups(uint16_t count, ambit_sport_mode_device_settings_t *ambit_settings);
+
+/**
+ * Allocates memmory for a number of display structures and
+ * initiate structure pointers to NULL and view_count to 0.
+ * \param count number of displays that will be allocated.
+ * \param ambit_sport_mode structure where these displays belongs to.
+ * The ambit_sport_mode will be updated to point at the allocated data and the display count will be set to count.
+ * \return true if allocation was succesfull.
+ */
+bool libambit_malloc_sport_mode_displays(uint16_t count, ambit_sport_mode_t *ambit_sport_mode);
+
+/**
+ * Allocates memmory for a number of views.
+ * \param count number of views that will be allocated.
+ * \param ambit_displays structure where these views belongs to.
+ * The ambit_displays will be updated to point at the allocated data and the views count will be set to count.
+ * \return true if allocation was succesfull.
+ */
+bool libambit_malloc_sport_mode_view(uint16_t count, ambit_sport_mode_display_t *ambit_displays);
+
+/**
+ * Allocates memmory for a number of app ids.
+ * \param count number of app_ids (uint32_t) that will be allocated.
+ * \param ambit_sport_mode structure where these app_ids belongs to.
+ * The ambit_sport_mode will be updated to point at the allocated data and the app_ids_count will be set to count.
+ * \return true if allocation was succesfull.
+ */
+bool libambit_malloc_sport_mode_app_ids(uint16_t count, ambit_sport_mode_t *ambit_sport_mode);
+
+/**
+ * Allocates memmory for a number of custom mode index.
+ * \param count number of custom mode index that will be allocated.
+ * \param ambit_sport_mode_group structure where these custom mode index belongs to.
+ * The ambit_sport_mode_group will be updated to point at the allocated data and the custom mode index count will be set to count.
+ * \return true if allocation was succesfull.
+ */
+bool libambit_malloc_sport_mode_index(uint16_t count, ambit_sport_mode_group_t *ambit_sport_mode_group);
+
+/**
+ * Free device setting and under laying data structures,
+ * allocated by ambit_maloc_*
+ * \param settings Device settings to free
+ */
+void libambit_sport_mode_device_settings_free(ambit_sport_mode_device_settings_t *settings);
+
+/**
+ * Free structures for app rules and under laying data,
+ * allocated by liblibambit_malloc_app_rules and libambit_malloc_app_rule
+ * \param app_rules structure to be freed
+ */
+void libambit_app_rules_free(ambit_app_rules_t *app_rules);
+
+/**
+ * Allocates memmory for ambit_app_rules_t structure and
+ * initiate pointer in the structure to NULL and app_rules_count to 0.
+ * \note Caller is responsible of freeing the struct with libambit_app_rules_free()
+ * \return pointer to allocated data struct.
+ */
+ambit_app_rules_t *liblibambit_malloc_app_rules(void);
+
+/**
+ * Allocates memmory for a number of app rules.
+ * \param count number of app rules that will be allocated.
+ * \param ambit_app_rules structure from where the app rules will be referenced from.
+ * The app_rule pointer in ambit_app_rules will be updated to point to the allocated data and the app_rules_count will be set to count.
+ * \return true if allocation was succesfull.
+ */
+bool libambit_malloc_app_rule(uint16_t count, ambit_app_rules_t *ambit_app_rules);
 
 #ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
 }
diff --git a/src/libambit/pmem20.c b/src/libambit/pmem20.c
index 53d216a..3f4e238 100644
--- a/src/libambit/pmem20.c
+++ b/src/libambit/pmem20.c
@@ -37,6 +37,8 @@
 #define PMEM20_LOG_HEADER_MIN_LEN                512 /* Header actually longer, but not interesting*/
 
 #define PMEM20_GPS_ORBIT_START            0x000704e0
+#define PMEM20_SPORT_MODE_START          0x00002000
+#define PMEM20_APP_START                  0x000927c0
 
 typedef struct __attribute__((__packed__)) periodic_sample_spec_s {
     uint16_t type;
@@ -56,6 +58,8 @@ static void add_time(ambit_date_time_t *intime, int32_t offset, ambit_date_time_
 static int is_leap(unsigned int y);
 static void to_timeval(ambit_date_time_t *ambit_time, struct timeval *timeval);
 
+static int libambit_pmem20_data_write(libambit_pmem20_t *object, const uint32_t start_address, const uint8_t *data, size_t datalen);
+
 /*
  * Static variables
  */
@@ -548,6 +552,45 @@ int libambit_pmem20_gps_orbit_write(libambit_pmem20_t *object, const uint8_t *da
     return ret;
 }
 
+int libambit_pmem20_data_write(libambit_pmem20_t *object, const uint32_t start_address, const uint8_t *data, size_t datalen)
+{
+    int ret = -1;
+    const uint8_t *bufptrs[1];
+    size_t bufsizes;
+    uint32_t address = start_address;
+    size_t offset = 0;
+
+    bufptrs[0] = data;
+    bufsizes = object->chunk_size;
+
+    // Write first chunk
+    ret = write_data_chunk(object->ambit_object, address, 1, bufptrs, &bufsizes);
+    offset += bufsizes;
+    address += object->chunk_size;
+
+    // Write rest of the chunks
+    while (ret == 0 && offset < datalen) {
+        bufptrs[0] = data + offset;
+        bufsizes = (datalen - offset > object->chunk_size ? object->chunk_size : datalen - offset);
+
+        ret = write_data_chunk(object->ambit_object, address, 1, bufptrs, &bufsizes);
+        offset += bufsizes;
+        address += bufsizes;
+    }
+
+    return ret;
+}
+
+int libambit_pmem20_sport_mode_write(libambit_pmem20_t *object, const uint8_t *data, size_t datalen, bool include_sha256_hash)
+{
+    return libambit_pmem20_data_write(object, PMEM20_SPORT_MODE_START, data, datalen);
+}
+
+int libambit_pmem20_app_data_write(libambit_pmem20_t *object, const uint8_t *data, size_t datalen, bool include_sha256_hash)
+{
+    return libambit_pmem20_data_write(object, PMEM20_APP_START, data, datalen);
+}
+
 /**
  * Parse the given sample
  * \return number of samples added (1 or 0)
@@ -830,7 +873,7 @@ static int parse_sample(uint8_t *buf, size_t offset, uint8_t **spec, ambit_log_e
           case 0x18:
             log_entry->samples[*sample_count].type = ambit_log_sample_type_activity;
             log_entry->samples[*sample_count].u.activity.activitytype = read16inc(buf, &int_offset);
-            log_entry->samples[*sample_count].u.activity.custommode = read32inc(buf, &int_offset);
+            log_entry->samples[*sample_count].u.activity.sportmode = read32inc(buf, &int_offset);
             break;
           case 0x1a:
             log_entry->samples[*sample_count].type = ambit_log_sample_type_cadence_source;
diff --git a/src/libambit/pmem20.h b/src/libambit/pmem20.h
index a59824e..92d3f6e 100644
--- a/src/libambit/pmem20.h
+++ b/src/libambit/pmem20.h
@@ -56,5 +56,7 @@ ambit_log_entry_t *libambit_pmem20_log_read_entry(libambit_pmem20_t *object);
 ambit_log_entry_t *libambit_pmem20_log_read_entry_address(libambit_pmem20_t *object, uint32_t address, uint32_t length);
 int libambit_pmem20_log_parse_header(uint8_t *data, size_t datalen, ambit_log_header_t *log_header);
 int libambit_pmem20_gps_orbit_write(libambit_pmem20_t *object, const uint8_t *data, size_t datalen, bool include_sha256_hash);
+int libambit_pmem20_sport_mode_write(libambit_pmem20_t *object, const uint8_t *data, size_t datalen, bool include_sha256_hash);
+int libambit_pmem20_app_data_write(libambit_pmem20_t *object, const uint8_t *data, size_t datalen, bool include_sha256_hash);
 
 #endif /* __PMEM20_H__ */
diff --git a/src/libambit/protocol.c b/src/libambit/protocol.c
index 3d318c6..26957db 100644
--- a/src/libambit/protocol.c
+++ b/src/libambit/protocol.c
@@ -106,7 +106,7 @@ int libambit_protocol_command(ambit_object_t *object, uint16_t command, uint8_t
     msg->MP = 0x5d;
     msg->parts_seq = htole16(packet_count);
     msg->command = htobe16(command);
-    msg->send_recv = htole16(legacy_format == 1 ? 1 : legacy_format == 2 ? 0x15 : 5);
+    msg->send_recv = htole16(legacy_format == 1 ? 1 : legacy_format == 2 ? 0x15 : legacy_format == 3 ? 0x0a : 5);
     msg->format = htole16(legacy_format == 1 ? 0 : 9);
     msg->sequence = htole16(object->sequence_no);
     msg->payload_len = htole32(datalen);
diff --git a/src/libambit/protocol.h b/src/libambit/protocol.h
index c57a181..a8e5729 100644
--- a/src/libambit/protocol.h
+++ b/src/libambit/protocol.h
@@ -32,8 +32,11 @@ enum ambit_commands_e {
     ambit_command_date                  = 0x0302,
     ambit_command_status                = 0x0306,
     ambit_command_personal_settings     = 0x0b00,
-    ambit_command_unknown2              = 0x0b02,
-    ambit_command_unknown1              = 0x0b04,
+    ambit_command_personal_settings_write = 0x0b01,
+    ambit_command_waypoint_count        = 0x0b02,
+    ambit_command_waypoint_read         = 0x0b03,
+    ambit_command_nav_memory_delete     = 0x0b04,
+    ambit_command_waypoint_write        = 0x0b05,
     ambit_command_log_count             = 0x0b06,
     ambit_command_log_head_first        = 0x0b07,
     ambit_command_log_head_peek         = 0x0b08,
diff --git a/src/libambit/sport_mode_serialize.c b/src/libambit/sport_mode_serialize.c
new file mode 100644
index 0000000..1f65fa2
--- /dev/null
+++ b/src/libambit/sport_mode_serialize.c
@@ -0,0 +1,459 @@
+#include "sport_mode_serialize.h"
+#include "libambit.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+const u_int8_t UNKNOWN_DISPLAYES[] =
+        {0x06,0x01,0x3e,0x00,0x07,0x01,0x04,0x00,0x11,0x01,0x04,0x00,0x08,0x01,0x08,0x00,0x09,0x01,0x04,0x00,0x00,0x00,0x08,0x00,0x08,0x01,0x08,0x00,0x09,0x01,0x04,0x00,0x01,0x00,0x08,0x00,0x08,0x01,0x1a,0x00,0x09,0x01,0x04,0x00,0x02,0x00,0x00,0x00,0x0a,0x01,0x02,0x00,0x10,0x00,0x0a,0x01,0x02,0x00,0x01,0x00,0x0a,0x01,0x02,0x00,0xfe,0xff
+        ,0x06,0x01,0x44,0x00,0x07,0x01,0x04,0x00,0x23,0x01,0x05,0x00,0x08,0x01,0x08,0x00,0x09,0x01,0x04,0x00,0x00,0x00,0x08,0x00,0x08,0x01,0x08,0x00,0x09,0x01,0x04,0x00,0x01,0x00,0x28,0x00,0x08,0x01,0x20,0x00,0x09,0x01,0x04,0x00,0x02,0x00,0x00,0x00,0x0a,0x01,0x02,0x00,0x10,0x00,0x0a,0x01,0x02,0x00,0x08,0x00,0x0a,0x01,0x02,0x00,0x01,0x00,0x0a,0x01,0x02,0x00,0xfe,0xff
+        ,0x06,0x01,0x3e,0x00,0x07,0x01,0x04,0x00,0x22,0x01,0x06,0x00,0x08,0x01,0x08,0x00,0x09,0x01,0x04,0x00,0x00,0x00,0x18,0x00,0x08,0x01,0x08,0x00,0x09,0x01,0x04,0x00,0x01,0x00,0x19,0x00,0x08,0x01,0x1a,0x00,0x09,0x01,0x04,0x00,0x02,0x00,0x00,0x00,0x0a,0x01,0x02,0x00,0x32,0x00,0x0a,0x01,0x02,0x00,0x1a,0x00,0x0a,0x01,0x02,0x00,0x10,0x00
+        ,0x06,0x01,0x08,0x00,0x07,0x01,0x04,0x00,0x50,0x01,0x07,0x00
+        ,0x06,0x01,0x4a,0x00,0x07,0x01,0x04,0x00,0x04,0x01,0x32,0x00,0x08,0x01,0x08,0x00,0x09,0x01,0x04,0x00,0x00,0x00,0x3e,0x00,0x08,0x01,0x08,0x00,0x09,0x01,0x04,0x00,0x01,0x00,0x3d,0x00,0x08,0x01,0x26,0x00,0x09,0x01,0x04,0x00,0x02,0x00,0x00,0x00,0x0a,0x01,0x02,0x00,0x05,0x00,0x0a,0x01,0x02,0x00,0x0a,0x00,0x0a,0x01,0x02,0x00,0x15,0x00,0x0a,0x01,0x02,0x00,0x0b,0x00,0x0a,0x01,0x02,0x00,0x1c,0x00};
+
+
+static void serialize_header(u_int16_t header_nbr, u_int16_t length, u_int8_t *dataWrite);
+static int serialize_sport_modes(ambit_sport_mode_device_settings_t *ambit_settings, u_int8_t *data);
+static int serialize_sport_mode(ambit_sport_mode_t *ambit_sport_mode, u_int8_t *data);
+static u_int8_t serialize_sport_mode_settings(ambit_sport_mode_settings_t *settings, u_int8_t *data);
+static int serialize_displays(ambit_sport_mode_t *ambit_sport_mode, u_int8_t *data);
+static int serialize_display(ambit_sport_mode_display_t *display, u_int8_t *data);
+static int serialize_display_layout(uint16_t displayType, u_int8_t *data);
+static int serialize_rows(ambit_sport_mode_display_t *display, u_int8_t *data);
+static int serialize_row_entry(u_int16_t row_nbr, u_int16_t row_item, u_int8_t *data);
+static int serialize_views(ambit_sport_mode_display_t *display, u_int8_t *data);
+static int serialize_view_entry(uint16_t view, u_int8_t *data);
+
+static int serialize_apps_index(ambit_sport_mode_t *ambit_sport_mode, u_int8_t *data);
+
+static int serialize_sport_mode_groups(ambit_sport_mode_device_settings_t *ambit_settings, u_int8_t *data);
+static int serialize_sport_mode_group(ambit_sport_mode_group_t *sport_mode_group, u_int8_t *data);
+static int serialize_name(char *activity_name, u_int8_t *data);
+static int serialize_activity_id(uint16_t activity_id, u_int8_t *data);
+static int serialize_modes_id(u_int16_t index, u_int8_t *data);
+
+int get_app_index(ambit_app_rules_t* ambit_apps, u_int32_t app_id)
+{
+    int foundIndex = -1;
+    int j = 0;
+
+    while(foundIndex==-1 && j<ambit_apps->app_rules_count) {
+        if (app_id == ambit_apps->app_rules[j].app_id) {
+            foundIndex = j;
+        }
+        j++;
+    }
+
+    if (foundIndex == -1) {
+        printf("Error. No apps found for specified app id = %d.\n", app_id);
+    }
+
+    return foundIndex;
+}
+
+u_int8_t calculate_app_rule_checksum(u_int8_t *data, u_int32_t data_length)
+{
+    u_int8_t checksum = 0;
+    int i;
+    for (i=0; i<data_length; i++) {
+        checksum ^= data[i];
+    }
+
+    checksum ^= data_length;
+
+    return checksum;
+}
+
+int calculate_size_for_serialize_app_data(ambit_sport_mode_device_settings_t *ambit_settings, ambit_app_rules_t* ambit_apps)
+{
+    u_int16_t nbr_of_apps = ambit_settings->app_ids_count;
+
+    if (nbr_of_apps==0) {
+        return 0;
+    }
+
+    // Add header size
+    u_int32_t serialize_buffer_size = sizeof(u_int32_t) * nbr_of_apps +7;
+
+    // Add size for all apps.
+    int i;
+    for (i=0; i<nbr_of_apps; i++) {
+        int app_index = get_app_index(ambit_apps, ambit_settings->app_ids[i]);
+        u_int32_t app_length = ambit_apps->app_rules[app_index].app_rule_data_length;
+        serialize_buffer_size += app_length + 1;
+    }
+
+    return serialize_buffer_size;
+}
+
+int serialize_app_data(ambit_sport_mode_device_settings_t *ambit_settings, ambit_app_rules_t* ambit_apps, uint8_t *data)
+{
+    u_int16_t nbr_of_apps = ambit_settings->app_ids_count;
+    if (nbr_of_apps==0) {
+        return 0;
+    }
+
+    u_int16_t header_length = sizeof(u_int32_t) * nbr_of_apps +7;
+    u_int8_t *writePosition = data;
+
+    writePosition[0] = nbr_of_apps & 0xff;
+    writePosition[1] = (nbr_of_apps >> 8) & 0xff;
+    writePosition[2] = nbr_of_apps ^0x02;
+    writePosition[3] = header_length & 0xff;
+    writePosition[4] = (header_length >> 8) & 0xff;
+    writePosition[5] = 0;
+    writePosition[6] = 0;
+
+    u_int32_t last_checksum_position = header_length;
+    u_int8_t *writeAppPosition = data + header_length;
+    int i;
+    for (i=0; i<nbr_of_apps; i++) {
+        int app_index = get_app_index(ambit_apps, ambit_settings->app_ids[i]);
+        u_int32_t app_length = ambit_apps->app_rules[app_index].app_rule_data_length;
+        last_checksum_position += app_length + 1;
+
+        // Write position of checksum for the app (in header).
+        writePosition[7+i*4] = last_checksum_position & 0xff;
+        writePosition[8+i*4] = (last_checksum_position >> 8) & 0xff;
+        writePosition[9+i*4] = (last_checksum_position >> 16) & 0xff;
+        writePosition[10+i*4] = (last_checksum_position >> 24) & 0xff;
+
+        // Copy app.
+        memcpy(writeAppPosition, ambit_apps->app_rules[app_index].app_rule_data, ambit_apps->app_rules[app_index].app_rule_data_length);
+
+        // Calculate and write checksum for app (at first byte after the app).
+        writeAppPosition[app_length] = calculate_app_rule_checksum(writeAppPosition, ambit_apps->app_rules[app_index].app_rule_data_length);
+        writeAppPosition += app_length + 1;
+    }
+
+    return writeAppPosition - data;
+}
+
+int calculate_size_for_serialize_sport_mode_device_settings(ambit_sport_mode_device_settings_t *ambit_device_settings)
+{
+    int serialize_buffer_size = 0;
+    int i, j;
+
+    serialize_buffer_size += HEADER_SIZE * 2;
+    serialize_buffer_size += 6; // For unknown data field;
+
+    // Add size for custom modes
+    for (i = 0; i < ambit_device_settings->sport_modes_count; i++) {
+        serialize_buffer_size += HEADER_SIZE;
+        serialize_buffer_size += HEADER_SIZE + sizeof(ambit_sport_mode_settings_t);
+
+        serialize_buffer_size += HEADER_SIZE;
+        // Add size for all displays
+        for (j = 0; j < ambit_device_settings->sport_modes[i].displays_count; j++) {
+            // Add size for type, row1 and row2 (including headers). (The needed space for some display types can be smaler).
+            serialize_buffer_size += 48;
+            // Add size for all views.
+            serialize_buffer_size += 6 * ambit_device_settings->sport_modes[i].display[j].views_count;
+        }
+        serialize_buffer_size += sizeof(UNKNOWN_DISPLAYES);
+
+        // Add size for apps index data
+        serialize_buffer_size += 10 * ambit_device_settings->sport_modes[i].apps_list_count;
+    }
+
+    // Add size for custom mode groups
+    serialize_buffer_size += HEADER_SIZE;
+    for (i=0; i<ambit_device_settings->sport_mode_groups_count; i++) {
+        serialize_buffer_size += 38;
+        serialize_buffer_size += 6 * ambit_device_settings->sport_mode_groups[i].sport_mode_index_count;
+    }
+
+    return serialize_buffer_size;
+}
+
+int serialize_sport_mode_device_settings(ambit_sport_mode_device_settings_t *ambit_settings, uint8_t *data)
+{
+    u_int8_t *writePosition;
+    writePosition = data + HEADER_SIZE; //Save space for header.
+
+    writePosition += serialize_sport_modes(ambit_settings, writePosition);
+
+    writePosition += serialize_sport_mode_groups(ambit_settings, writePosition);
+
+    serialize_header(0x0003, writePosition - data - 4, data);
+
+    return writePosition - data;
+}
+
+static void serialize_header(u_int16_t header_nbr, u_int16_t length, u_int8_t *dataWrite)
+{
+    ambit_write_header_t *header = (ambit_write_header_t*)dataWrite;
+    header->header = header_nbr;
+    header->length = length;
+}
+
+static int serialize_unknown_data_field(u_int8_t *data)
+{
+    serialize_header(0x010b, 2, data);
+    data += 4;
+    *(u_int16_t *)data = 2;
+
+    return 4 + 2;
+}
+
+static int serialize_sport_modes(ambit_sport_mode_device_settings_t *ambit_settings, u_int8_t *data)
+{
+    u_int8_t *writePosition = data + HEADER_SIZE; //Save space for header.
+
+    writePosition += serialize_unknown_data_field(writePosition);
+    int i;
+    ambit_sport_mode_t *sport_mode = ambit_settings->sport_modes;
+    for (i = 0; i < ambit_settings->sport_modes_count; i++) {
+        writePosition += serialize_sport_mode(sport_mode, writePosition);
+        sport_mode++;
+    }
+
+    // Write header at the end, when total data size is known.
+    serialize_header(SPORT_MODE_START_HEADER, writePosition - data - 4, data);
+
+    return writePosition - data;
+}
+
+static int serialize_sport_mode(ambit_sport_mode_t *ambit_sport_mode, u_int8_t *data)
+{
+    u_int8_t *dataWrite = data + HEADER_SIZE;
+
+    dataWrite += serialize_sport_mode_settings(&(ambit_sport_mode->settings), dataWrite);
+    dataWrite += serialize_displays(ambit_sport_mode, dataWrite);
+    if(ambit_sport_mode->apps_list_count) {
+        dataWrite += serialize_apps_index(ambit_sport_mode, dataWrite);
+    }
+
+    serialize_header(SPORT_MODE_HEADER, dataWrite - data - HEADER_SIZE, data);
+
+    return dataWrite - data;
+}
+
+static u_int8_t serialize_sport_mode_settings(ambit_sport_mode_settings_t *settings, u_int8_t *data)
+{
+    serialize_header(SETTINGS_HEADER, SETTINGS_SIZE, data);
+
+    memcpy(data + HEADER_SIZE, settings, sizeof(ambit_sport_mode_settings_t));
+
+    return SETTINGS_SIZE + HEADER_SIZE;
+}
+
+static int serialize_displays(ambit_sport_mode_t *ambit_sport_mode, u_int8_t *data)
+{
+    u_int8_t *writePosition;
+    writePosition = data + HEADER_SIZE; //Save space for header.
+
+    int i;
+    ambit_sport_mode_display_t *display = ambit_sport_mode->display;
+    for (i = 0; i < ambit_sport_mode->displays_count; i++) {
+        writePosition += serialize_display(display, writePosition);
+        display++;
+    }
+
+    memcpy(writePosition, UNKNOWN_DISPLAYES, sizeof(UNKNOWN_DISPLAYES));
+    writePosition += sizeof(UNKNOWN_DISPLAYES);
+
+    serialize_header(DISPLAYS_HEADER, writePosition - data - HEADER_SIZE, data);
+
+    return writePosition - data;
+}
+
+static int serialize_apps_index(ambit_sport_mode_t *ambit_sport_mode, u_int8_t *data)
+{
+    serialize_header(0x010c, ambit_sport_mode->apps_list_count * 10, data);
+
+    u_int8_t *writePosition;
+    writePosition = data + HEADER_SIZE; //Save space for header.
+
+    u_int16_t i;
+    for(i=0; i<ambit_sport_mode->apps_list_count ;i++) {
+        serialize_header(0x010d, 6, writePosition);
+        writePosition += HEADER_SIZE;
+
+        u_int16_t *write16Position = (u_int16_t*)writePosition;
+        write16Position[0] = ambit_sport_mode->apps_list[i].index;
+        write16Position[1] = 1;
+        write16Position[2] = ambit_sport_mode->apps_list[i].logging;
+        writePosition += 6;
+    }
+
+    return HEADER_SIZE + ambit_sport_mode->apps_list_count * 10;
+}
+
+static int serialize_display(ambit_sport_mode_display_t *display, u_int8_t *data)
+{
+    u_int8_t *writePosition;
+    writePosition = data + HEADER_SIZE; //Save space for header.
+
+    writePosition += serialize_display_layout(display->type, writePosition);
+    writePosition += serialize_rows(display, writePosition);
+
+    serialize_header(DISPLAY_HEADER, writePosition - data - HEADER_SIZE, data);
+
+    return writePosition - data;
+}
+
+static int serialize_display_layout(uint16_t displayType, u_int8_t *data)
+{
+    ambit_sport_mode_display_layout_t *layout = (ambit_sport_mode_display_layout_t *)data;
+    layout->header = DISPLAY_LAYOUT_HEADER;
+    layout->length = 4;
+    layout->display_layout = displayType;
+    layout->unknown[0] = 0x0a;
+    layout->unknown[1] = 0;
+
+    return sizeof(ambit_sport_mode_display_layout_t);
+}
+
+static int serialize_rows(ambit_sport_mode_display_t *display, u_int8_t *data)
+{
+    u_int8_t *writePosition = data + HEADER_SIZE; //Save space for header.
+
+    switch (display->type) {
+    case SINGLE_ROW_DISPLAY_TYPE:
+    {
+        writePosition += serialize_row_entry(0, display->row1, writePosition);
+        serialize_header(ROWS_HEADER, writePosition - data - HEADER_SIZE, data);
+        break;
+    }
+    case DOUBLE_ROWS_DISPLAY_TYPE:
+    {
+        writePosition += serialize_row_entry(0, display->row1, writePosition);
+        serialize_header(ROWS_HEADER, writePosition - data - HEADER_SIZE, data);
+
+        u_int8_t *headerPosition = writePosition;
+        writePosition += HEADER_SIZE; //Save space for second line header.
+        writePosition += serialize_row_entry(1, display->row2, writePosition);
+        writePosition += serialize_views(display, writePosition);
+        serialize_header(ROWS_HEADER, writePosition - headerPosition - HEADER_SIZE, headerPosition);
+        break;
+    }
+    case TRIPLE_ROWS_DISPLAY_TYPE:
+    case GRAPH_DISPLAY_TYPE:
+    {
+        writePosition += serialize_row_entry(0, display->row1, writePosition);
+        serialize_header(ROWS_HEADER, writePosition - data - HEADER_SIZE, data);
+
+        u_int8_t *headerPosition = writePosition;
+        writePosition += HEADER_SIZE; //Save space for second line header.
+        writePosition += serialize_row_entry(1, display->row2, writePosition);
+        serialize_header(ROWS_HEADER, writePosition - headerPosition - HEADER_SIZE, headerPosition);
+
+        headerPosition = writePosition;
+        writePosition += HEADER_SIZE; //Save space for third line header.
+        writePosition += serialize_row_entry(2, display->row3, writePosition);
+        writePosition += serialize_views(display, writePosition);
+        serialize_header(ROWS_HEADER, writePosition - headerPosition - HEADER_SIZE, headerPosition);
+        break;
+    }
+    default:
+        break;
+    }
+
+    return writePosition - data;
+}
+
+static int serialize_row_entry(u_int16_t row_nbr, u_int16_t row_item, u_int8_t *data)
+{
+    ambit_sport_mode_row_t *row = (ambit_sport_mode_row_t *)data;
+    row->header = ROW_HEADER;
+    row->length = 4;
+    row->row_nbr = row_nbr;
+    row->item = row_item;
+
+    return sizeof(ambit_sport_mode_row_t);
+}
+
+static int serialize_views(ambit_sport_mode_display_t *display, u_int8_t *data)
+{
+    u_int8_t *writePosition = data;
+    uint16_t *view = display->view;
+
+    int i;
+    for (i = 0; i < display->views_count; i++) {
+        writePosition += serialize_view_entry(*view, writePosition);
+        view++;
+    }
+
+    return writePosition - data;
+}
+
+static int serialize_view_entry(uint16_t view, u_int8_t *data)
+{
+    ambit_sport_mode_view_t *ambitView = (ambit_sport_mode_view_t *)data;
+    ambitView->header = VIEW_HEADER;
+    ambitView->length = 2;
+    ambitView->item = view;
+
+    return sizeof(ambit_sport_mode_view_t);
+}
+
+static int serialize_sport_mode_groups(ambit_sport_mode_device_settings_t *ambit_settings, u_int8_t *data)
+{
+    u_int8_t *writePosition = data + HEADER_SIZE; //Save space for header.
+
+    int i;
+    ambit_sport_mode_group_t *sport_mode_group = ambit_settings->sport_mode_groups;
+    for (i = 0; i < ambit_settings->sport_mode_groups_count; i++) {
+        writePosition += serialize_sport_mode_group(sport_mode_group, writePosition);
+        sport_mode_group++;
+    }
+
+    // Write header at the end, when total data size is known.
+    serialize_header(SPORT_MODE_GROUP_START_HEADER, writePosition - data - 4, data);
+
+    return writePosition - data;
+}
+
+static int serialize_sport_mode_group(ambit_sport_mode_group_t *sport_mode_group, u_int8_t *data)
+{
+    u_int8_t *dataWrite = data + HEADER_SIZE;
+
+    dataWrite += serialize_name(sport_mode_group->activity_name, dataWrite);
+    dataWrite += serialize_activity_id(sport_mode_group->activity_id, dataWrite);
+
+    int i;
+    uint16_t *group_index = sport_mode_group->sport_mode_index;
+    for (i = 0; i < sport_mode_group->sport_mode_index_count; i++) {
+        dataWrite += serialize_modes_id(*group_index, dataWrite);
+        group_index++;
+    }
+
+    serialize_header(SPORT_MODE_GROUP_HEADER, dataWrite - data - HEADER_SIZE, data);
+
+    return dataWrite - data;
+}
+
+static int serialize_name(char *activity_name, u_int8_t *data)
+{
+    u_int8_t *dataWrite = data + HEADER_SIZE;
+
+    char *str = (char*)dataWrite;
+    memcpy(str, activity_name, GROUP_NAME_SIZE);
+
+    serialize_header(NAME_HEADER, GROUP_NAME_SIZE, data);
+
+    return GROUP_NAME_SIZE + HEADER_SIZE;
+}
+
+static int serialize_activity_id(uint16_t activity_id, u_int8_t *data)
+{
+    u_int8_t *dataWrite = data + HEADER_SIZE;
+
+    *(u_int16_t*)dataWrite = activity_id;
+    serialize_header(ACTIVITY_ID_HEADER, sizeof(u_int16_t), data);
+
+    return sizeof(u_int16_t) + HEADER_SIZE;
+}
+
+static int serialize_modes_id(u_int16_t index, u_int8_t *data)
+{
+    serialize_header(MODES_ID_HEADER, sizeof(u_int16_t), data);
+    data += HEADER_SIZE;
+
+    // Write the IDs/position/index for all the custom mode that is in this group.
+    *(u_int16_t*)data = index;
+
+    return sizeof(u_int16_t) + HEADER_SIZE;
+}
diff --git a/src/libambit/sport_mode_serialize.h b/src/libambit/sport_mode_serialize.h
new file mode 100644
index 0000000..87f372a
--- /dev/null
+++ b/src/libambit/sport_mode_serialize.h
@@ -0,0 +1,69 @@
+/*
+ * (C) Copyright 2014 Emil Ljungdahl
+ *
+ * This file is part of libambit.
+ *
+ * libambit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Contributors:
+ *
+ */
+#ifndef __SPORT_MODE_SERIALIZE_H__
+#define __SPORT_MODE_SERIALIZE_H__
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include "libambit.h"
+
+
+static const int HEADER_SIZE = 4;
+static const int ACTIVITY_NAME_SIZE = 16;
+static const int GROUP_NAME_SIZE = 24;
+static const int SETTINGS_SIZE = 90;
+
+static const int SPORT_MODE_START_HEADER = 0x0100;
+static const int SPORT_MODE_HEADER = 0x0101;
+static const int SETTINGS_HEADER = 0x0102;
+static const int DISPLAYS_HEADER = 0x0105;
+static const int DISPLAY_HEADER = 0x0106;
+static const int DISPLAY_LAYOUT_HEADER = 0x0107;
+static const int ROWS_HEADER = 0x0108;
+static const int ROW_HEADER = 0x0109;
+static const int VIEW_HEADER = 0x010a;
+
+static const int SPORT_MODE_GROUP_START_HEADER = 0x0200;
+static const int SPORT_MODE_GROUP_HEADER = 0x0210;
+static const int NAME_HEADER = 0x0212;
+static const int ACTIVITY_ID_HEADER = 0x0213;
+static const int MODES_ID_HEADER = 0x0214;
+
+#define SINGLE_ROW_DISPLAY_TYPE 0x0106
+#define DOUBLE_ROWS_DISPLAY_TYPE 0x0105
+#define TRIPLE_ROWS_DISPLAY_TYPE 0x0104
+#define GRAPH_DISPLAY_TYPE 0x0101
+
+int calculate_size_for_serialize_sport_mode_device_settings(ambit_sport_mode_device_settings_t *ambit_device_settings);
+int serialize_sport_mode_device_settings(ambit_sport_mode_device_settings_t *ambit_settings, uint8_t *data);
+int calculate_size_for_serialize_app_data(ambit_sport_mode_device_settings_t *ambit_settings, ambit_app_rules_t *ambit_apps);
+int serialize_app_data(ambit_sport_mode_device_settings_t *ambit_settings, ambit_app_rules_t *ambit_apps, uint8_t *data);
+
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif /* __SPORT_MODE_SERIALIZE_H__ */
diff --git a/src/movescount/CMakeLists.txt b/src/movescount/CMakeLists.txt
index d9cdd28..e11fbda 100644
--- a/src/movescount/CMakeLists.txt
+++ b/src/movescount/CMakeLists.txt
@@ -24,13 +24,17 @@ project(movescount CXX)
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
 set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../openambit/cmake")
 
-find_package(Qt4 REQUIRED
-  COMPONENTS QtCore QtNetwork)
-find_package(QJSON 0.8.0 REQUIRED)
+if(USE_QT5)
+  find_package(Qt5Core REQUIRED)
+  find_package(Qt5Network REQUIRED)
+else(USE_QT5)
+  find_package(Qt4 REQUIRED
+    COMPONENTS QtCore QtNetwork)
+  find_package(QJSON 0.8.0 REQUIRED)
+endif(USE_QT5)
 find_package(ZLIB REQUIRED)
 find_package(libambit REQUIRED)
 
-include(${QT_USE_FILE})
 include(GNUInstallDirs)
 
 set(CMAKE_AUTOMOC ON)
@@ -40,16 +44,19 @@ include_directories(
   ../libambit/
   ${QJSON_INCLUDE_DIR}
   ${ZLIB_INCLUDE_DIRS}
-  )
+)
 
 link_directories(
   ../libambit/
-  )
+)
 
-add_library (
+add_library(
   movescount
   SHARED
   deviceinfo.cpp
+  sportmode.cpp
+  sportmodegroup.cpp
+  movescountsettings.cpp
   logentry.cpp
   logstore.cpp
   movescount.cpp
@@ -59,24 +66,28 @@ add_library (
   movescountlogchecker.cpp
   )
 
+if(USE_QT5)
+  QT5_USE_MODULES(movescount Core Network)
+else(USE_QT5)
+  QT4_USE_MODULES(movescount Core Network)
+endif(USE_QT5)
+
 target_link_libraries(
   movescount
   ${LIBAMBIT_LIBS}
   ${QJSON_LIBRARIES}
   ${ZLIB_LIBRARIES}
-  Qt4::QtNetwork
-  Qt4::QtCore
-  )
+)
 
 set_target_properties(movescount
   PROPERTIES
   VERSION 0.3.0
   SOVERSION 0
-  )
+)
 install(TARGETS
   movescount
   DESTINATION ${CMAKE_INSTALL_LIBDIR}
-  )
+)
 install(FILES
   deviceinfo.h
   logentry.h
@@ -84,4 +95,4 @@ install(FILES
   movescount.h
   movescountxml.h
   DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/movescount
-  )
+)
diff --git a/src/movescount/logentry.h b/src/movescount/logentry.h
index 89bb842..f9fec27 100644
--- a/src/movescount/logentry.h
+++ b/src/movescount/logentry.h
@@ -44,10 +44,6 @@ public:
     DeviceInfo deviceInfo;
     ambit_personal_settings_t *personalSettings;
     ambit_log_entry_t *logEntry;
-signals:
-    
-public slots:
-    
 };
 
 #endif // LOGENTRY_H
diff --git a/src/movescount/logstore.cpp b/src/movescount/logstore.cpp
index dc33042..390e8a8 100644
--- a/src/movescount/logstore.cpp
+++ b/src/movescount/logstore.cpp
@@ -1077,7 +1077,7 @@ void LogStore::XMLReader::readLogSamples()
                             logEntry->logEntry->samples[sampleCount].u.activity.activitytype = xml.readElementText().toUInt();
                         }
                         else if (xml.name() == "CustomModeId") {
-                            logEntry->logEntry->samples[sampleCount].u.activity.custommode = xml.readElementText().toUInt();
+                            logEntry->logEntry->samples[sampleCount].u.activity.sportmode = xml.readElementText().toUInt();
                         }
                         else {
                             /* Should not get here! */
@@ -1728,7 +1728,7 @@ bool LogStore::XMLWriter::writeLogSample(ambit_log_sample_t *sample)
     case ambit_log_sample_type_activity:
     {
         xml.writeTextElement("ActivityType", QString("%1").arg(sample->u.activity.activitytype));
-        xml.writeTextElement("CustomModeId", QString("%1").arg(sample->u.activity.custommode));
+        xml.writeTextElement("CustomModeId", QString("%1").arg(sample->u.activity.sportmode));
         break;
     }
     case ambit_log_sample_type_cadence_source:
diff --git a/src/movescount/movescount.cpp b/src/movescount/movescount.cpp
index 9b24537..86f4bcf 100644
--- a/src/movescount/movescount.cpp
+++ b/src/movescount/movescount.cpp
@@ -21,6 +21,9 @@
  */
 #include "movescount.h"
 #include <QtNetwork/QNetworkRequest>
+#ifdef QT_DEBUG
+#include <QtNetwork/QSslConfiguration>
+#endif
 #include <QEventLoop>
 #include <QMutex>
 #include <QDebug>
@@ -128,17 +131,49 @@ int MovesCount::getOrbitalData(u_int8_t **data)
     return ret;
 }
 
-int MovesCount::getPersonalSettings(ambit_personal_settings_t *settings)
+int MovesCount::getPersonalSettings(ambit_personal_settings_t *settings, bool onlychangedsettings)
 {
     int ret = -1;
 
     if (&workerThread == QThread::currentThread()) {
-        ret = getPersonalSettingsInThread(settings);
+        ret = getPersonalSettingsInThread(settings, onlychangedsettings);
     }
     else {
         QMetaObject::invokeMethod(this, "getPersonalSettingsInThread", Qt::BlockingQueuedConnection,
                                   Q_RETURN_ARG(int, ret),
-                                  Q_ARG(ambit_personal_settings_t *, settings));
+                                  Q_ARG(ambit_personal_settings_t *, settings), Q_ARG(bool, onlychangedsettings));
+    }
+
+    return ret;
+}
+
+int MovesCount::getRoute(ambit_route_t *route, ambit_personal_settings_t *ps, QString url)
+{
+    int ret = -1;
+
+    if (&workerThread == QThread::currentThread()) {
+        ret = getRouteInThread(route, ps, url);
+    }
+    else {
+        QMetaObject::invokeMethod(this, "getRouteInThread", Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(int, ret),
+                                  Q_ARG(ambit_route_t *, route),Q_ARG(ambit_personal_settings_t *, ps) , Q_ARG(QString, url));
+    }
+
+    return ret;
+}
+
+int MovesCount::getRoutePoints(ambit_route_t *route, ambit_personal_settings_t *ps, QString url)
+{
+    int ret = -1;
+
+    if (&workerThread == QThread::currentThread()) {
+        ret = getRoutePointsInThread(route, ps, url);
+    }
+    else {
+        QMetaObject::invokeMethod(this, "getRoutePointsInThread", Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(int, ret),
+                                  Q_ARG(ambit_route_t *, route),Q_ARG(ambit_personal_settings_t *, ps), Q_ARG(QString, url));
     }
 
     return ret;
@@ -149,6 +184,38 @@ void MovesCount::getDeviceSettings()
     QMetaObject::invokeMethod(this, "getDeviceSettingsInThread", Qt::AutoConnection);
 }
 
+int MovesCount::getCustomModeData(ambit_sport_mode_device_settings_t* ambitCustomModes)
+{
+    int ret = -1;
+
+    if (&workerThread == QThread::currentThread()) {
+        ret = getCustomModeDataInThread(ambitCustomModes);
+    }
+    else {
+        QMetaObject::invokeMethod(this, "getCustomModeDataInThread", Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(int, ret),
+                                  Q_ARG(ambit_sport_mode_device_settings_t*, ambitCustomModes));
+    }
+
+    return ret;
+}
+
+int MovesCount::getAppsData(ambit_app_rules_t* ambitApps)
+{
+    int ret = -1;
+
+    if (&workerThread == QThread::currentThread()) {
+        ret = getAppsDataInThread(ambitApps);
+    }
+    else {
+        QMetaObject::invokeMethod(this, "getAppsDataInThread", Qt::BlockingQueuedConnection,
+                                  Q_RETURN_ARG(int, ret),
+                                  Q_ARG(ambit_app_rules_t*, ambitApps));
+    }
+
+    return ret;
+}
+
 QList<MovesCountLogDirEntry> MovesCount::getMovescountEntries(QDate startTime, QDate endTime)
 {
     QList<MovesCountLogDirEntry> retList;
@@ -264,9 +331,128 @@ int MovesCount::getOrbitalDataInThread(u_int8_t **data)
     return ret;
 }
 
-int MovesCount::getPersonalSettingsInThread(ambit_personal_settings_t *settings)
+int MovesCount::getPersonalSettingsInThread(ambit_personal_settings_t *settings, bool onlychangedsettings)
+{
+    int ret = -1;
+    QNetworkReply *reply;
+
+    reply = syncGET("/userdevices/" + QString("%1").arg(device_info.serial), QString("onlychangedsettings=%1&includeallsportmodes=false&model=%2&eswverrsion=%3.%4.%5").arg((onlychangedsettings?"true":"fasle")).arg(device_info.model).arg(device_info.fw_version[0]).arg(device_info.fw_version[1]).arg(device_info.fw_version[2]), true);
+
+    if(reply->error() == QNetworkReply::NoError) {
+        QByteArray _data = reply->readAll();
+
+        if (_data.length() > 0) {
+            jsonParser.parsePersonalSettings(_data, settings, this);
+            ret = _data.length();
+        }
+    }
+
+    delete reply;
+
+    return ret;
+}
+
+int MovesCount::getRouteInThread(ambit_route_t *route, ambit_personal_settings_t *ps, QString url)
 {
-    Q_UNUSED(settings);
+
+    int ret = -1;
+    QNetworkReply *reply;
+
+    reply = syncGET("/" + url, "", true);
+
+    if(reply->error() == QNetworkReply::NoError) {
+        QByteArray _data = reply->readAll();
+
+        if (_data.length() > 0) {
+            jsonParser.parseRoute(_data, route, ps, this);
+            ret = _data.length();
+        }
+    }
+
+    delete reply;
+
+    return ret;
+}
+
+int MovesCount::getRoutePointsInThread(ambit_route_t *route, ambit_personal_settings_t *ps, QString url)
+{
+
+    int ret = -1;
+    QNetworkReply *reply;
+
+    reply = syncGET("/" + url, "type=routepoints&maxpoints=1000", true);
+
+    if(reply->error() == QNetworkReply::NoError) {
+        QByteArray _data = reply->readAll();
+
+        if (_data.length() > 0) {
+            ret = jsonParser.parseRoutePoints(_data, route, ps);
+        }
+    }
+
+    delete reply;
+
+    return ret;
+}
+
+int MovesCount::applyPersonalSettingsFromDevice(ambit_personal_settings_t *movesPersonalSettings, ambit_personal_settings_t *devicePersonalSettings)
+{
+
+    //TODO: resolve name conflict, rename device waypoint?
+    bool device_waypoint_has_changes = false;
+    int  device_waypoint_num_changes = 0; //this value is only a control value for allocating memory if device_waypoint_has_changes
+    int  device_waypoint_count = devicePersonalSettings->waypoints.count;
+    int  moves_waypoint_count = movesPersonalSettings->waypoints.count;
+
+    for(int x=0; x<device_waypoint_count; x++) {
+        if(devicePersonalSettings->waypoints.data[x].status == 2) { //Waypoint marked for removal
+            for(int y=0; y<moves_waypoint_count; y++) {
+                if(strncmp(devicePersonalSettings->waypoints.data[x].name, movesPersonalSettings->waypoints.data[y].name,49) == 0 && strncmp(devicePersonalSettings->waypoints.data[x].route_name, movesPersonalSettings->waypoints.data[y].route_name,49) == 0) {
+                    devicePersonalSettings->waypoints.data[x].status = 0;
+                    movesPersonalSettings->waypoints.data[x].status = 2; //Mark for actual removal
+                    device_waypoint_has_changes = true;
+                    device_waypoint_num_changes--;
+                }
+            }
+        } else if(devicePersonalSettings->waypoints.data[x].status == 1) { //Waypoint marked for addition;
+            for(int y=0; y<moves_waypoint_count; y++) {
+                if(strncmp(devicePersonalSettings->waypoints.data[x].name, movesPersonalSettings->waypoints.data[y].name,49) == 0 && strncmp(devicePersonalSettings->waypoints.data[x].route_name, movesPersonalSettings->waypoints.data[y].route_name,49) == 0) {
+                    movesPersonalSettings->waypoints.data[x].status = 2; //Marked for removal due to name conflict (device win)
+                }
+
+            }
+            device_waypoint_has_changes = true;
+            device_waypoint_num_changes++;
+        }
+    }
+
+    if(device_waypoint_has_changes) {
+        int new_waypoint_count = moves_waypoint_count+device_waypoint_num_changes;
+        int new_added = 0;
+        ambit_waypoint_t *new_waypoints = (ambit_waypoint_t *)malloc(sizeof(ambit_waypoint_t)*new_waypoint_count);
+
+        for(int x=0; x<moves_waypoint_count && new_added<new_waypoint_count; x++) {
+            if(movesPersonalSettings->waypoints.data[x].status == 0) {
+                new_waypoints[new_added] = movesPersonalSettings->waypoints.data[x];
+                ++new_added;
+            }
+        }
+
+        for(int x=0; x<device_waypoint_count && new_added<new_waypoint_count; x++) {
+            if(devicePersonalSettings->waypoints.data[x].status == 1) {
+                new_waypoints[new_added] = devicePersonalSettings->waypoints.data[x];
+                ++new_added;
+            }
+        }
+
+        if(movesPersonalSettings->waypoints.data != NULL) {
+            free(movesPersonalSettings->waypoints.data);
+        }
+
+        movesPersonalSettings->waypoints.data = new_waypoints;
+        movesPersonalSettings->waypoints.count = new_waypoint_count;
+    }
+
     return 0;
 }
 
@@ -281,6 +467,44 @@ void MovesCount::getDeviceSettingsInThread()
     }
 }
 
+int MovesCount::getCustomModeDataInThread(ambit_sport_mode_device_settings_t *ambitSettings)
+{
+    int ret = -1;
+    QNetworkReply *reply;
+
+    reply = syncGET("/userdevices/" + device_info.serial, "", true);
+
+    if (checkReplyAuthorization(reply)) {
+        QByteArray _data = reply->readAll();
+        MovescountSettings settings = MovescountSettings();
+
+        if (jsonParser.parseDeviceSettingsReply(_data, settings) == 0) {
+            settings.toAmbitData(ambitSettings);
+            ret = 0;
+        }
+    }
+
+    return ret;
+}
+
+int MovesCount::getAppsDataInThread(ambit_app_rules_t* ambitApps)
+{
+    int ret = -1;
+    QNetworkReply *reply;
+
+    reply = syncGET("/rules/private", "", true);
+
+    if (checkReplyAuthorization(reply)) {
+        QByteArray _data = reply->readAll();
+
+        if (jsonParser.parseAppRulesReply(_data, ambitApps) == 0) {
+            ret = 0;
+        }
+    }
+
+    return ret;
+}
+
 QList<MovesCountLogDirEntry> MovesCount::getMovescountEntriesInThread(QDate startTime, QDate endTime)
 {
     QNetworkReply *reply;
@@ -322,7 +546,17 @@ void MovesCount::checkLatestFirmwareVersionInThread()
 
 void MovesCount::writePersonalSettingsInThread(ambit_personal_settings_t *settings)
 {
-    Q_UNUSED(settings);
+    QByteArray json_settings;
+    QNetworkReply *reply;
+
+    jsonParser.generateNewPersonalSettings(settings, device_info, json_settings);
+    reply = syncPUT("/userdevices/" + QString("%1").arg(device_info.serial), "resetchangedsettings=true", json_settings, true);
+
+    if(reply->error() == QNetworkReply::NoError) {
+        QByteArray _data = reply->readAll();
+    } else {
+        qDebug() << QString("writePersonalSettingsInThread error: ") << reply->error();
+    }
 }
 
 void MovesCount::writeLogInThread(LogEntry *logEntry)
@@ -340,14 +574,16 @@ void MovesCount::writeLogInThread(LogEntry *logEntry)
 
     reply = syncPOST("/moves/", "", output, true);
 
-    if (reply->error() == QNetworkReply::NoError) {
+    if (reply->error() == QNetworkReply::NoError || reply->error() == QNetworkReply::UnknownContentError) {
         QByteArray data = reply->readAll();
         if (jsonParser.parseLogReply(data, moveId) == 0) {
             emit logMoveID(logEntry->device, logEntry->time, moveId);
+        } else {
+            qDebug() << "Failed to upload log, movescount.com replied with \"" << reply->readAll() << "\"";
         }
-    }
+    } 
     else {
-        qDebug() << "Failed to upload log, movescount.com replied with \"" << reply->readAll() << "\"";
+        qDebug() << "Failed to upload log (err code:" << reply->error() << "), movescount.com replied with \"" << reply->readAll() << "\"";
     }
 }
 
@@ -397,6 +633,12 @@ QNetworkReply *MovesCount::asyncGET(QString path, QString additionalHeaders, boo
         url += "&" + additionalHeaders;
     }
 
+    #ifdef QT_DEBUG
+    qDebug() << "asyncGet: " << url;
+    QSslConfiguration ssl_config = QSslConfiguration::defaultConfiguration();
+    ssl_config.setPeerVerifyMode(QSslSocket::VerifyNone);
+    QSslConfiguration::setDefaultConfiguration(ssl_config);
+    #endif
     req.setRawHeader("User-Agent", "ArREST v1.0");
     req.setUrl(QUrl(url));
 
@@ -427,6 +669,12 @@ QNetworkReply *MovesCount::asyncPOST(QString path, QString additionalHeaders, QB
         url += "&" + additionalHeaders;
     }
 
+    #ifdef QT_DEBUG
+    qDebug() << "asyncPost: " << url;
+    QSslConfiguration ssl_config = QSslConfiguration::defaultConfiguration();
+    ssl_config.setPeerVerifyMode(QSslSocket::VerifyNone);
+    QSslConfiguration::setDefaultConfiguration(ssl_config);
+    #endif
     req.setRawHeader("User-Agent", "ArREST v1.0");
     req.setRawHeader("Content-Type", "application/json");
     req.setUrl(QUrl(url));
@@ -446,6 +694,43 @@ QNetworkReply *MovesCount::syncPOST(QString path, QString additionalHeaders, QBy
     return reply;
 }
 
+QNetworkReply *MovesCount::asyncPUT(QString path, QString additionalHeaders, QByteArray &postData, bool auth)
+{
+    QNetworkRequest req;
+    QString url = this->baseAddress + path + "?appkey=" + this->appkey;
+
+    if (auth) {
+        url += "&userkey=" + this->userkey + "&email=" + this->username;
+    }
+    if (additionalHeaders.length() > 0) {
+        url += "&" + additionalHeaders;
+    }
+
+    #ifdef QT_DEBUG
+    qDebug() << "asyncPut: " << url;
+    QSslConfiguration ssl_config = QSslConfiguration::defaultConfiguration();
+    ssl_config.setPeerVerifyMode(QSslSocket::VerifyNone);
+    QSslConfiguration::setDefaultConfiguration(ssl_config);
+    #endif
+    req.setRawHeader("User-Agent", "ArREST v1.0");
+    req.setRawHeader("Content-Type", "application/json");
+    req.setUrl(QUrl(url));
+
+    return this->manager->put(req, postData);
+}
+
+QNetworkReply *MovesCount::syncPUT(QString path, QString additionalHeaders, QByteArray &postData, bool auth)
+{
+    QNetworkReply *reply;
+
+    reply = asyncPUT(path, additionalHeaders, postData, auth);
+    QEventLoop loop;
+    connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
+    loop.exec();
+
+    return reply;
+}
+
 #ifdef QT_DEBUG
 #include <QDir>
 void MovesCount::writeJsonToStorage(QString filename, QByteArray &data)
diff --git a/src/movescount/movescount.h b/src/movescount/movescount.h
index f599d64..09b6383 100644
--- a/src/movescount/movescount.h
+++ b/src/movescount/movescount.h
@@ -54,8 +54,13 @@ public:
 
     bool isAuthorized();
     int getOrbitalData(u_int8_t **data);
-    int getPersonalSettings(ambit_personal_settings_t *settings);
+    int getPersonalSettings(ambit_personal_settings_t *settings, bool onlychangedsettings);
+    int getRoute(ambit_route_t *routes, ambit_personal_settings_t *ps, QString url);
+    int getRoutePoints(ambit_route_t *routes, ambit_personal_settings_t *ps, QString url);
+    int applyPersonalSettingsFromDevice(ambit_personal_settings_t *movesPersonalSettings, ambit_personal_settings_t *devicePersonalSettings);
     void getDeviceSettings();
+    int getCustomModeData(ambit_sport_mode_device_settings_t *ambitCustomModes);
+    int getAppsData(ambit_app_rules_t *ambitApps);
     QList<MovesCountLogDirEntry> getMovescountEntries(QDate startTime, QDate endTime);
 
     void checkAuthorization();
@@ -75,8 +80,12 @@ private slots:
     void handleAuthorizationSignal(bool authorized);
 
     int getOrbitalDataInThread(u_int8_t **data);
-    int getPersonalSettingsInThread(ambit_personal_settings_t *settings);
+    int getPersonalSettingsInThread(ambit_personal_settings_t *settings, bool onlychangedsettings);
+    int getRouteInThread(ambit_route_t *routes, ambit_personal_settings_t *ps, QString url);
+    int getRoutePointsInThread(ambit_route_t *routes, ambit_personal_settings_t *ps, QString url);
     void getDeviceSettingsInThread();
+    int getCustomModeDataInThread(ambit_sport_mode_device_settings_t *ambitSettings);
+    int getAppsDataInThread(ambit_app_rules_t *ambitApps);
     QList<MovesCountLogDirEntry> getMovescountEntriesInThread(QDate startTime, QDate endTime);
 
     void checkAuthorizationInThread();
@@ -96,6 +105,9 @@ private:
     QNetworkReply *asyncPOST(QString path, QString additionalHeaders, QByteArray &postData, bool auth);
     QNetworkReply *syncPOST(QString path, QString additionalHeaders, QByteArray &postData, bool auth);
 
+    QNetworkReply *asyncPUT(QString path, QString additionalHeaders, QByteArray &postData, bool auth);
+    QNetworkReply *syncPUT(QString path, QString additionalHeaders, QByteArray &postData, bool auth);
+
 #ifdef QT_DEBUG
     void writeJsonToStorage(QString filename, QByteArray &data);
 #endif
diff --git a/src/movescount/movescountjson.cpp b/src/movescount/movescountjson.cpp
index 9656d5b..72563b8 100644
--- a/src/movescount/movescountjson.cpp
+++ b/src/movescount/movescountjson.cpp
@@ -19,15 +19,26 @@
  * Contributors:
  *
  */
+#include "movescount.h"
 #include "movescountjson.h"
 
 #include <QRegExp>
 #include <QVariantMap>
 #include <QVariantList>
-#include <qjson/parser.h>
-#include <qjson/serializer.h>
+#include <QStringList>
+#include <QDebug>
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+# include <qjson/parser.h>
+# include <qjson/serializer.h>
+#else
+# include <QJsonArray>
+# include <QJsonDocument>
+# include <QJsonObject>
+#endif
 #include <zlib.h>
 #include <math.h>
+#include <stdio.h>
+#include <algorithm>
 
 MovesCountJSON::MovesCountJSON(QObject *parent) :
     QObject(parent)
@@ -36,15 +47,14 @@ MovesCountJSON::MovesCountJSON(QObject *parent) :
 
 int MovesCountJSON::parseFirmwareVersionReply(QByteArray &input, u_int8_t fw_version[3])
 {
-    QJson::Parser parser;
-    bool ok;
     QRegExp rx("([0-9]+)\\.([0-9]+)\\.([0-9]+)");
 
     if (input.length() <= 0) {
         return -1;
     }
 
-    QVariantMap result = parser.parse(input, &ok).toMap();
+    bool ok = false;
+    QVariantMap result = parseJsonMap(input, ok);
 
     if (ok && result["LatestFirmwareVersion"].toString().length() > 0) {
         if (rx.indexIn(result["LatestFirmwareVersion"].toString()) >= 0) {
@@ -60,14 +70,12 @@ int MovesCountJSON::parseFirmwareVersionReply(QByteArray &input, u_int8_t fw_ver
 
 int MovesCountJSON::parseLogReply(QByteArray &input, QString &moveId)
 {
-    QJson::Parser parser;
-    bool ok;
-
     if (input.length() <= 0) {
         return -1;
     }
 
-    QVariantMap result = parser.parse(input, &ok).toMap();
+    bool ok = false;
+    QVariantMap result = parseJsonMap(input, ok);
 
     if (ok && result["MoveID"].toString().length() > 0 && result["MoveID"].toString() != "0") {
         moveId = result["MoveID"].toString();
@@ -77,18 +85,302 @@ int MovesCountJSON::parseLogReply(QByteArray &input, QString &moveId)
     return -1;
 }
 
-int MovesCountJSON::parseLogDirReply(QByteArray &input, QList<MovesCountLogDirEntry> &entries)
+int MovesCountJSON::parsePersonalSettings(QByteArray &input, ambit_personal_settings_t *ps, MovesCount *movescount)
 {
-    QJson::Parser parser;
-    QVariantList logList;
 
-    bool ok;
+    if (input.length() <= 0) {
+        return -1;
+    }
+
+    bool ok = false;
+    QVariantMap result = parseJsonMap(input, ok);
+
+	 if(!ok) {
+        return -1;
+    }
+
+    //Empty waypoints in personal_settings (ps)
+    ps->waypoints.count = 0;
+    if(ps->waypoints.data != NULL) free(ps->waypoints.data);
+
+    if(ps->routes.count == 0 && result["RouteURIs"].type() == QVariant::String) {
+        QStringList routes = result["RouteURIs"].toString().split(',');
+        ps->routes.count = routes.size();
+        ps->routes.data  = libambit_route_alloc(ps->routes.count);
+        for(int x=0; x<routes.size(); x++) {
+            movescount->getRoute(&(ps->routes.data[x]), ps, routes.value(x));
+        }
+
+        //Sort routes on name
+        QStringList qslist_route_name;
+        uint16_t sort_offset = 0;
+        ambit_route_t *routes_sorted = (ambit_route_t*)calloc(ps->routes.count,sizeof(ambit_route_t));
+
+        for(int x=0; x < ps->routes.count;++x) {
+            qslist_route_name.append(QString(ps->routes.data[x].name));
+        }
+
+        qslist_route_name.sort();
+        for(int k=0, s=qslist_route_name.size(), max=(s/2); k<max; k++) qslist_route_name.swap(k,s-(1+k));
+
+        for(int x=0; x < qslist_route_name.size(); ++x) {
+            for(int y = 0; y < ps->routes.count;++y) {
+                if(qslist_route_name.at(x).compare(QString(ps->routes.data[y].name)) == 0) {
+                    routes_sorted[sort_offset++] = ps->routes.data[y];
+                    break;
+                }
+            }
+        }
+
+        free(ps->routes.data);
+        ps->routes.data = routes_sorted;
+
+    }
+
+    if(result["Waypoints"].type() == QVariant::List && result["Waypoints"].toList().count()>0) {
+        ambit_waypoint_t *waypoints_to_append = NULL;
+        uint8_t num_to_append = (uint8_t)result["Waypoints"].toList().count();
+
+
+        waypoints_to_append = (ambit_waypoint_t*)malloc(sizeof(ambit_waypoint_t)*num_to_append);
+
+        for(int x=0; x<num_to_append; x++) {
+            QDateTime dt;
+            QVariantMap jsonWp = result["Waypoints"].toList().at(x).toMap();
+            waypoints_to_append[x].altitude = (uint16_t)jsonWp["Altitude"].toInt();
+            waypoints_to_append[x].longitude = (uint32_t)(jsonWp["Longitude"].toFloat()*10000000);
+            waypoints_to_append[x].latitude = (uint32_t)(jsonWp["Latitude"].toFloat()*10000000);
+            waypoints_to_append[x].type = (uint8_t)(jsonWp["Type"].toInt());
+            this->copyDataString(jsonWp["Name"],waypoints_to_append[x].name, 49);
+            strncpy(waypoints_to_append[x].route_name, "", 49);
+            dt = dt.fromString(jsonWp["CreationLocalTime"].toString(), Qt::ISODate);
+            waypoints_to_append[x].ctime_second = (uint8_t)dt.toString("s").toInt();
+            waypoints_to_append[x].ctime_minute = (uint8_t)dt.toString("m").toInt();
+            waypoints_to_append[x].ctime_hour = (uint8_t)dt.toString("h").toInt();
+            waypoints_to_append[x].ctime_day = (uint8_t)dt.toString("d").toInt();
+            waypoints_to_append[x].ctime_month = (uint8_t)dt.toString("M").toInt();
+            waypoints_to_append[x].ctime_year = (uint16_t)dt.toString("yyyy").toInt();
+        }
+
+        libambit_waypoint_append(ps, waypoints_to_append, num_to_append);
+        free(waypoints_to_append);
+    }
+
+    //Sort waypoints on route_name
+    QStringList qslist_route_name;
+    QString last = "";
+    uint16_t sort_offset = 0;
+    ambit_waypoint_t *wp_sorted = (ambit_waypoint_t*)calloc(ps->waypoints.count,sizeof(ambit_waypoint_t));
+
+    for(int x=0; x < ps->waypoints.count;++x) {
+        if(x == 0 || last.compare(QString(ps->waypoints.data[x].route_name)) !=0 ) {
+            last = QString(ps->waypoints.data[x].route_name);
+            qslist_route_name.append(last);
+        }
+    }
+
+    qslist_route_name.sort();
+
+    for(int x=0; x < qslist_route_name.size(); ++x) {
+        for(int y = 0; y < ps->waypoints.count;++y) {
+            if(qslist_route_name.at(x).compare(QString(ps->waypoints.data[y].route_name)) == 0) {
+                wp_sorted[sort_offset++] = ps->waypoints.data[y];
+            }
+        }
+    }
+
+    free(ps->waypoints.data);
+    ps->waypoints.data = wp_sorted;
+
+    return 0;
+}
+
+bool MovesCountJSON::copyDataString(QVariant entry, char *data, size_t maxlength)
+{
+    QByteArray ba=entry.toString().toLatin1();
+    strncpy(data, ba.data(), maxlength);
+    return true;
+}
+
+int MovesCountJSON::parseRoute(QByteArray &input, ambit_route_t *route, ambit_personal_settings_t *ps, MovesCount *movescount)
+{
+    if (input.length() <= 0) {
+        return -1;
+    }
+
+    bool ok = false;
+    QVariantMap result = parseJsonMap(input, ok);
+    QString name = "";
+
+	 if(!ok) {
+        return -1;
+    }
+
+    if(result["RoutePointsCount"].type() == QVariant::ULongLong) {
+        route->points_count = (uint16_t)result["RoutePointsCount"].toInt();
+    }
+
+    route->id = result["RouteID"].toUInt();
+    strncpy(route->name, result["Name"].toString().toLatin1().data(),49);
+    route->waypoint_count = result["WaypointCount"].toUInt();
+
+    int ret;
+
+    if(result["RoutePointsURI"].type() == QVariant::String) {
+        if((ret = movescount->getRoutePoints(route, ps, result["RoutePointsURI"].toString())) < 2) {
+            if(route->points != NULL) {
+                free(route->points);
+                route->points = NULL;
+            }
+            route->points_count = 0;
+            return -1;
+        }
+
+        route->points_count = ret;
+    } else {
+        return -1;
+    }
+
+    route->activity_id = result["ActivityID"].toUInt();
+    route->altitude_dec = result["DescentAltitude"].toUInt();
+    route->altitude_asc= result["AscentAltitude"].toUInt();
+    route->distance = result["Distance"].toUInt();
+
+    //TODO: Remove
+    //libambit_debug_route_print(route);
+
+    return (int)route->points_count;
+}
+
+int MovesCountJSON::parseRoutePoints(QByteArray &input, ambit_route_t *route, ambit_personal_settings_t *ps)
+{
+    //Todo: Implement compressed and json routepoints. It looks like yo have to tell the uiservices-api to use
+    //      the other format specific, so no hurry to implement.
+    int ret = -1;
+
+    if (input.length() <= 0) {
+        return -1;
+    }
+
+    bool ok = false;
+    QVariantMap result = parseJsonMap(input, ok);
+    QVariantList jsonRoutePoints;
+    int32_t clat = 0, clon=0;
+    uint16_t cur_waypoint_count = 0;
+
+    if(!ok) {
+        return -1;
+    }
+
+    if(result["CompressedRoutePoints"].type() == QVariant::String && result["CompressedRoutePoints"].toString() != "") {
+        qDebug() << "Is Compressed data";
+        //gunzip data
+        return -2; //Should not be possible
+    }
+
+    if(result["RoutePoints"].type() == QVariant::List && result["RoutePoints"].toList().size() > 1) {
+        jsonRoutePoints = result["RoutePoints"].toList();
+    }
+
+    if(jsonRoutePoints.size()>1) {
+
+        route->points = (ambit_routepoint_t*)malloc(jsonRoutePoints.size()*sizeof(ambit_routepoint_t));
+        for(int x=0; x<jsonRoutePoints.size(); ++x) {
+            QVariantMap jCurrent = jsonRoutePoints.at(x).toMap();
+            clat = (int32_t)(jCurrent["Latitude"].toDouble()*10000000);
+            clon = (int32_t)(jCurrent["Longitude"].toDouble()*10000000);
+            appendRoutePoint(route, x, clat, clon, jCurrent["Altitude"].toInt(), (uint32_t)(jCurrent["RelativeDistance"].toDouble()*100000));
+
+            if(jCurrent["Name"].toString() != "") {
+                appendWaypoint(cur_waypoint_count, ps, QString(route->name), jCurrent["Name"].toString(), clat, clon, jCurrent["Altitude"].toInt(), jCurrent["Type"].toInt());
+                ++cur_waypoint_count;
+            }
+        }
+
+        ret = jsonRoutePoints.size();
+
+    } else if (result["Points"].type() == QVariant::String && result["Points"].toString() != "") {
+        /* This format does not support waypoints */
+        QStringList strPointsList = result["Points"].toString().split(';');
+        route->points = (ambit_routepoint_t*)malloc(strPointsList.size()*sizeof(ambit_routepoint_t));
+        for(int x = 0; x<strPointsList.size();++x) {
+            QStringList strPointArray = strPointsList.at(x).split(',');
+            clat = (int32_t)(strPointArray.at(0).toDouble()*10000000);
+            clon = (int32_t)(strPointArray.at(1).toDouble()*10000000);
+            appendRoutePoint(route, x, clat, clon, strPointArray.at(2).toInt(), (uint32_t)strPointArray.at(3).toDouble()*100000);
+        }
+        ret = strPointsList.size();
+    } else {
+        return -1;
+    }
+
+    route->end_lat = route->points[(ret-1)].lat;
+    route->end_lon = route->points[(ret-1)].lon;
+
+    route->mid_lat = route->max_lat - (route->max_lat - route->min_lat)/2;
+    route->mid_lon = route->max_lon - (route->max_lon - route->min_lon)/2;
+
+    if(cur_waypoint_count == 0) {
+        appendWaypoint(cur_waypoint_count++, ps, QString(route->name), "A", route->start_lat, route->start_lon, route->points[0].altitude, movescount_waypoint_type_internal_wp_start);
+        appendWaypoint(cur_waypoint_count, ps, QString(route->name), "B", route->end_lat, route->end_lon, route->points[(ret-1)].altitude, movescount_waypoint_type_internal_wp_end);
+    }
+
+    return ret;
+}
+
+bool MovesCountJSON::appendRoutePoint(ambit_route_t *route, int point_number, int32_t lat, int32_t lon, int32_t altitude, uint32_t distance)
+{
+    if(point_number == 0) {
+        route->start_lat = lat;
+        route->start_lon = lon;
+        route->max_lat = route->start_lat;
+        route->min_lat = route->start_lat;
+        route->max_lon = route->start_lon;
+        route->min_lon = route->start_lon;
+    }
 
+    //This is needed to calculate route->mid_lat and route->mid_lon
+    if(lat > route->max_lat) route->max_lat = lat;
+    if(lat < route->min_lat) route->min_lat = lat;
+    if(lon > route->max_lon) route->max_lon = lon;
+    if(lon < route->min_lon) route->min_lon = lon;
+
+    route->points[point_number].lat = lat;
+    route->points[point_number].lon = lon;
+    route->points[point_number].altitude = altitude;
+    route->points[point_number].distance = distance;
+
+    return true;
+}
+
+bool MovesCountJSON::appendWaypoint(uint16_t count, ambit_personal_settings_t *ps, QString route_name, QString waypoint_name, int32_t lat, int32_t lon, uint16_t altitude, uint8_t type) {
+
+    ambit_waypoint_t wp;
+    wp.index = 0;
+    strncpy(wp.name, waypoint_name.toLatin1().data(), 49);
+    strncpy(wp.route_name, route_name.toLatin1().data(), 49);
+    wp.ctime_second = count;
+    wp.ctime_minute = wp.ctime_hour = 0;
+    wp.ctime_day = wp.ctime_month = 1;
+    wp.ctime_year = 1980;
+    wp.latitude = lat;
+    wp.longitude = lon;
+    wp.altitude = altitude;
+    wp.type = type;
+    wp.status = 0;
+    libambit_waypoint_append(ps, &wp, 1);
+
+    return true;
+}
+
+int MovesCountJSON::parseLogDirReply(QByteArray &input, QList<MovesCountLogDirEntry> &entries)
+{
     if (input.length() <= 0) {
         return -1;
     }
 
-    logList = parser.parse(input, &ok).toList();
+    bool ok = false;
+    QVariantMap logList = parseJsonMap(input, ok);
 
     if (ok) {
         foreach(QVariant entryVar, logList) {
@@ -102,6 +394,117 @@ int MovesCountJSON::parseLogDirReply(QByteArray &input, QList<MovesCountLogDirEn
     return -1;
 }
 
+int MovesCountJSON::generateNewPersonalSettings(ambit_personal_settings_t *settings, DeviceInfo &device_info, QByteArray &output)
+{
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+    QJson::Serializer serializer;
+    serializer.setDoublePrecision(16);
+    serializer.setIndentMode(QJson::IndentCompact);
+#endif
+    bool ok;
+    QVariantMap content;
+
+    content.insert("DeviceName", device_info.model);
+    content.insert("FirmwareVersion", QString("%1.%2.%3")
+            .arg(device_info.fw_version[0]).arg(device_info.fw_version[1])
+            .arg(device_info.fw_version[2]));
+    content.insert("HardwareVersion", QString("%1.%2.%3")
+            .arg(device_info.hw_version[0]).arg(device_info.hw_version[1])
+            .arg(device_info.hw_version[2]));
+    content.insert("SerialNumber", device_info.serial);
+
+    QVariantList waypoints;
+
+    if(settings->waypoints.count>0) {
+
+        QVariantMap c_waypoint;
+
+        for(int x=0; x < settings->waypoints.count; x++) {
+            if(settings->waypoints.data[x].route_name[0] == '\0') {
+                c_waypoint.clear();
+                c_waypoint.insert("Altitude", settings->waypoints.data[x].altitude);
+                c_waypoint.insert("CreationLocalTime", QString("%1-%2-%3T%4:%5:%6.0")
+                        .arg(settings->waypoints.data[x].ctime_year, 4, 10, QLatin1Char('0'))
+                        .arg(settings->waypoints.data[x].ctime_month, 2, 10, QLatin1Char('0'))
+                        .arg(settings->waypoints.data[x].ctime_day, 2, 10, QLatin1Char('0'))
+                        .arg(settings->waypoints.data[x].ctime_hour, 2, 10, QLatin1Char('0'))
+                        .arg(settings->waypoints.data[x].ctime_minute, 2, 10, QLatin1Char('0'))
+                        .arg(settings->waypoints.data[x].ctime_second, 2, 10, QLatin1Char('0'))
+                        );
+                c_waypoint.insert("Latitude",  (double)settings->waypoints.data[x].latitude/10000000);
+                c_waypoint.insert("Longitude",  (double)settings->waypoints.data[x].longitude/10000000);
+                c_waypoint.insert("Name", QString(settings->waypoints.data[x].name));
+                c_waypoint.insert("Type", settings->waypoints.data[x].type);
+                waypoints.append(c_waypoint);
+
+            }
+        }
+    }
+
+    content.insert("Waypoints", waypoints);
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+    output = serializer.serialize(content, &ok);
+#else
+    output = QJsonDocument(QJsonObject::fromVariantMap(content)).toJson(QJsonDocument::Compact);
+    ok = !output.isEmpty();
+#endif
+
+    return (ok ? 0 : -1);
+}
+
+int MovesCountJSON::parseDeviceSettingsReply(QByteArray &input, MovescountSettings &movescountSettings)
+{
+    bool ok;
+    QVariantMap entry = parseJsonMap(input, ok);
+
+    if (ok) {
+        QVariantMap settingsMap = entry["Settings"].toMap();
+        movescountSettings.parse(settingsMap);
+
+        return 0;
+    }
+
+    return -1;
+}
+
+int MovesCountJSON::parseAppRulesReply(QByteArray &input, ambit_app_rules_t* ambitApps)
+{
+    bool ok;
+    QVariantList appRulesList = parseJsonList(input, ok);
+
+    if (ok) {
+
+        QList<uint> appRulesId;
+        QList<QByteArray> appRulesData;
+        foreach(QVariant entryVar, appRulesList) {
+            QVariantMap entry = entryVar.toMap();
+            appRulesId.append(entry["RuleID"].toUInt());
+            QByteArray binary;
+            foreach (QVariant binaryVar, entry["Binary"].toList()) {
+                binary.append(binaryVar.toChar());
+            }
+            appRulesData.append(binary);
+        }
+
+        if (libambit_malloc_app_rule(appRulesId.count(), ambitApps)) {
+            int i = 0;
+            for (i=0; i<appRulesId.count(); i++) {
+                ambitApps->app_rules[i].app_id = appRulesId.at(i);
+                ambitApps->app_rules[i].app_rule_data_length = appRulesData.at(i).count();
+
+                ambitApps->app_rules[i].app_rule_data = (uint8_t*)malloc(appRulesData.at(i).count());
+                if (ambitApps->app_rules[i].app_rule_data != NULL) {
+                    memcpy(ambitApps->app_rules[i].app_rule_data, appRulesData.at(i).data(), appRulesData.at(i).count());
+                }
+            }
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
 /**
  * @brief MovesCountJSON::generateLogData
  * @param logEntry
@@ -118,7 +521,11 @@ int MovesCountJSON::parseLogDirReply(QByteArray &input, QList<MovesCountLogDirEn
  */
 int MovesCountJSON::generateLogData(LogEntry *logEntry, QByteArray &output)
 {
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
     QJson::Serializer serializer;
+    serializer.setDoublePrecision(16);
+    serializer.setIndentMode(QJson::IndentCompact);
+#endif
     bool ok, inPause = false;
     QVariantMap content;
     QVariantList IBIContent;
@@ -374,9 +781,6 @@ int MovesCountJSON::generateLogData(LogEntry *logEntry, QByteArray &output)
         }
     }
 
-    serializer.setDoublePrecision(16);
-    serializer.setIndentMode(QJson::IndentCompact);
-
     content.insert("ActivityID", logEntry->logEntry->header.activity_type);
     content.insert("AscentAltitude", (double)logEntry->logEntry->header.ascent);
     content.insert("AscentTime", (double)logEntry->logEntry->header.ascent_time/1000.0);
@@ -398,7 +802,11 @@ int MovesCountJSON::generateLogData(LogEntry *logEntry, QByteArray &output)
         content.insert("HighAltitude", QVariant::Invalid);
     }
     if (IBIContent.count() > 0) {
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
         uncompressedData = serializer.serialize(IBIContent);
+#else
+        uncompressedData = QJsonDocument(QJsonArray::fromVariantList(IBIContent)).toJson(QJsonDocument::Compact);
+#endif
         compressData(uncompressedData, compressedData);
         QVariantMap IBIDataMap;
         IBIDataMap.insert("CompressedValues", compressedData.toBase64());
@@ -421,7 +829,11 @@ int MovesCountJSON::generateLogData(LogEntry *logEntry, QByteArray &output)
     content.insert("PeakTrainingEffect", (double)logEntry->logEntry->header.peak_training_effect/10.0);
     content.insert("RecoveryTime", (double)logEntry->logEntry->header.recovery_time/1000.0);
     if (periodicSamplesContent.count() > 0) {
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
         uncompressedData = serializer.serialize(periodicSamplesContent);
+#else
+        uncompressedData = QJsonDocument(QJsonArray::fromVariantList(periodicSamplesContent)).toJson(QJsonDocument::Compact);
+#endif
         compressData(uncompressedData, compressedData);
         QVariantMap periodicSamplesDataMap;
         periodicSamplesDataMap.insert("CompressedSampleSets", compressedData.toBase64());
@@ -431,14 +843,23 @@ int MovesCountJSON::generateLogData(LogEntry *logEntry, QByteArray &output)
     content.insert("StartLatitude", QVariant::Invalid);
     content.insert("StartLongitude", QVariant::Invalid);
     if (GPSSamplesContent.count() > 0) {
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
         uncompressedData = serializer.serialize(GPSSamplesContent);
+#else
+        uncompressedData = QJsonDocument(QJsonArray::fromVariantList(GPSSamplesContent)).toJson(QJsonDocument::Compact);
+#endif
         compressData(uncompressedData, compressedData);
         QVariantMap GPSSamplesDataMap;
         GPSSamplesDataMap.insert("CompressedTrackPoints", compressedData.toBase64());
         content.insert("Track", GPSSamplesDataMap);                   /* compressed */
     }
 
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
     output = serializer.serialize(content, &ok);
+#else
+    output = QJsonDocument(QJsonObject::fromVariantMap(content)).toJson(QJsonDocument::Compact);
+    ok = !output.isEmpty();
+#endif
 
     return (ok ? 0 : -1);
 }
@@ -754,3 +1175,40 @@ QDateTime MovesCountJSON::dateTimeCompensate(QDateTime dateTime, QDateTime prevD
     }
     return dateTime;
 }
+
+QVariantMap MovesCountJSON::parseJsonMap(const QByteArray& input, bool& ok) const
+{
+    if (input.length() <= 0) {
+      ok = false;
+      return QVariantMap();
+    }
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+    QJson::Parser parser;
+    return parser.parse(input, &ok).toMap();
+#else
+    QJsonParseError err;
+    QJsonDocument json = QJsonDocument::fromJson(input, &err);
+    ok = !json.isNull();
+    return json.object().toVariantMap();
+#endif
+}
+
+QVariantList MovesCountJSON::parseJsonList(const QByteArray& input, bool& ok) const
+{
+    if (input.length() <= 0) {
+      ok = false;
+      return QVariantList();
+    }
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+    QJson::Parser parser;
+    return parser.parse(input, &ok).toList();
+#else
+    QJsonParseError err;
+    QJsonDocument json = QJsonDocument::fromJson(input, &err);
+    ok = !json.isNull();
+    return json.array().toVariantList();
+#endif
+}
+
diff --git a/src/movescount/movescountjson.h b/src/movescount/movescountjson.h
index f16405a..064251a 100644
--- a/src/movescount/movescountjson.h
+++ b/src/movescount/movescountjson.h
@@ -28,7 +28,11 @@
 #include <libambit.h>
 
 #include "logentry.h"
+#include "movescount.h"
 #include "movescountlogdirentry.h"
+#include "movescountsettings.h"
+
+class MovesCount;
 
 class MovesCountJSON : public QObject
 {
@@ -39,21 +43,33 @@ public:
     int parseFirmwareVersionReply(QByteArray &input, u_int8_t fw_version[3]);
     int parseLogReply(QByteArray &input, QString &moveId);
     int parseLogDirReply(QByteArray &input, QList<MovesCountLogDirEntry> &entries);
+    int parsePersonalSettings(QByteArray &input, ambit_personal_settings_t *ps, MovesCount *movescount);
+    int parseRoute(QByteArray &input, ambit_route_t *routes, ambit_personal_settings_t *ps, MovesCount *movescount);
+    int parseRoutePoints(QByteArray &input, ambit_route_t *routes, ambit_personal_settings_t *ps);
+    bool appendWaypoint(uint16_t count, ambit_personal_settings_t *ps, QString route_name, QString waypoint_name, int32_t lat, int32_t lon, uint16_t altitude, uint8_t type);
+    int parseDeviceSettingsReply(QByteArray &input, MovescountSettings &movescountSettings);
+    int parseAppRulesReply(QByteArray &input, ambit_app_rules_t* ambitApps); // QList<uint> &appRulesId, QList<QByteArray> &appRulesData);
 
+    int generateNewPersonalSettings(ambit_personal_settings_t *settings, DeviceInfo &device_info, QByteArray &output);
     int generateLogData(LogEntry *logEntry, QByteArray &output);
-    
+
 signals:
-    
+
 public slots:
 
 private:
     bool writePeriodicSample(ambit_log_sample_t *sample, QVariantMap &output);
+    bool copyDataString(QVariant entry, char *data, size_t maxlength);
+    bool appendRoutePoint(ambit_route_t *route, int point_number, int32_t lat, int32_t lon, int32_t altitude, uint32_t distance);
 
     int compressData(QByteArray &content, QByteArray &output);
     QList<int> rearrangeSamples(LogEntry *logEntry);
     QString dateTimeString(QDateTime dateTime);
     QDateTime dateTimeRound(QDateTime dateTime, int msecRoundFactor);
     QDateTime dateTimeCompensate(QDateTime dateTime, QDateTime prevDateTime, int minOffset);
+
+    QVariantMap parseJsonMap(const QByteArray& input, bool& ok) const;
+    QVariantList parseJsonList(const QByteArray& input, bool& ok) const;
 };
 
 #endif // MOVESCOUNTJSON_H
diff --git a/src/movescount/movescountsettings.cpp b/src/movescount/movescountsettings.cpp
new file mode 100644
index 0000000..2ecc0d8
--- /dev/null
+++ b/src/movescount/movescountsettings.cpp
@@ -0,0 +1,70 @@
+#include "movescountsettings.h"
+
+MovescountSettings::MovescountSettings(QObject *parent) :
+    QObject(parent)
+{
+
+}
+
+void MovescountSettings::parse(QVariantMap settingsMap)
+{
+    QList<u_int16_t> customModeIndex;
+    foreach (QVariant customModeVar, settingsMap["CustomModes"].toList()) {
+        QVariantMap customModeMap = customModeVar.toMap();
+
+        CustomMode customMode(customModeMap, this);
+        customModes.append(customMode);
+
+        customModeIndex.append(customMode.getCustomModeId());
+    }
+    foreach (QVariant customModeGroupVar, settingsMap["CustomModeGroups"].toList()) {
+        QVariantMap customModeGroupMap = customModeGroupVar.toMap();
+
+        CustomModeGroup customModeGroup(customModeGroupMap, this);
+        customModeGroups.append(customModeGroup);
+    }
+
+    for (int i = 0; i < customModeGroups.count(); i++) {
+        customModeGroups[i].setCustomModeIndex(customModeIndex);
+    }
+}
+
+MovescountSettings::MovescountSettings(const MovescountSettings &other) :
+    QObject(other.parent()),
+    customModeGroups(other.customModeGroups),
+    customModes(other.customModes)
+{
+}
+
+MovescountSettings& MovescountSettings::operator=(MovescountSettings &rhs)
+{
+    customModeGroups = rhs.customModeGroups;
+    customModes = rhs.customModes;
+
+    return *this;
+}
+
+void MovescountSettings::toAmbitData(ambit_sport_mode_device_settings_t *ambitSettings)
+{
+    // Copy Custom modes
+    if (libambit_malloc_sport_modes(customModes.count(), ambitSettings)) {
+        ambit_sport_mode_t *ambitCustomModes = ambitSettings->sport_modes;
+
+        foreach(CustomMode customMode, customModes)
+        {
+            customMode.toAmbitCustomModeData(ambitCustomModes, ambitSettings);
+            ambitCustomModes++;
+        }
+    }
+
+    // Copy Custom mode Groups
+    if (libambit_malloc_sport_mode_groups(customModeGroups.count(), ambitSettings)) {
+        ambit_sport_mode_group_t *ambitCustomModeGroups = ambitSettings->sport_mode_groups;
+
+        foreach(CustomModeGroup customModeGroup, customModeGroups)
+        {
+            customModeGroup.toAmbitData(ambitCustomModeGroups);
+            ambitCustomModeGroups++;
+        }
+    }
+}
diff --git a/src/movescount/movescountsettings.h b/src/movescount/movescountsettings.h
new file mode 100644
index 0000000..21f024a
--- /dev/null
+++ b/src/movescount/movescountsettings.h
@@ -0,0 +1,31 @@
+#ifndef MOVESCOUNTSETTINGS_H
+#define MOVESCOUNTSETTINGS_H
+
+#include <QObject>
+#include <QList>
+
+#include "sportmode.h"
+#include "sportmodegroup.h"
+
+class MovescountSettings : public QObject
+{
+    Q_OBJECT
+public:
+    explicit MovescountSettings(QObject *parent = 0);
+
+    void parse(QVariantMap settingsMap);
+    MovescountSettings(const MovescountSettings &other);
+
+    MovescountSettings& operator=(MovescountSettings &rhs);
+
+    void toAmbitData(ambit_sport_mode_device_settings_t *ambitSettings);
+signals:
+
+public slots:
+
+private:
+    QList<CustomModeGroup> customModeGroups;
+    QList<CustomMode> customModes;
+};
+
+#endif // MOVESCOUNTSETTINGS_H
diff --git a/src/movescount/movescountxml.cpp b/src/movescount/movescountxml.cpp
index 0b72408..937e650 100644
--- a/src/movescount/movescountxml.cpp
+++ b/src/movescount/movescountxml.cpp
@@ -572,7 +572,7 @@ bool MovesCountXML::XMLWriter::writeLogSample(ambit_log_sample_t *sample, QList<
         xml.writeTextElement("Time", QString::number((double)sample->time/1000.0, 'g', 16));
         xml.writeStartElement("Events");
         xml.writeStartElement("Activity");
-        xml.writeTextElement("CustomModeId", QString("%1").arg(sample->u.activity.custommode));
+        xml.writeTextElement("CustomModeId", QString("%1").arg(sample->u.activity.sportmode));
         xml.writeStartElement("Type");
         typename_lookup_entry_t *name_lookup;
         for (name_lookup = &sampleActivityNames[0]; name_lookup->XMLName != ""; name_lookup++) {
diff --git a/src/movescount/sportmode.cpp b/src/movescount/sportmode.cpp
new file mode 100644
index 0000000..2ec9a54
--- /dev/null
+++ b/src/movescount/sportmode.cpp
@@ -0,0 +1,443 @@
+#include "sportmode.h"
+#include "libambit.h"
+
+const QString CustomMode::ACTIVITY_ID = "ActivityID";
+const QString CustomMode::ALTI_BARO_MODE = "AltiBaroMode";
+const QString CustomMode::AUTOLAP_DISTANCE = "AutolapDistance";
+const QString CustomMode::GPS_INTERVAL = "GPSInterval";
+const QString CustomMode::HR_LIMIT_HIGH = "HRLimitHigh";
+const QString CustomMode::HR_LIMIT_LOW = "HRLimitLow";
+const QString CustomMode::INTERVAL_1_DISTANCE = "Interval1Distance";
+const QString CustomMode::INTERVAL_2_DISTANCE = "Interval2Distance";
+const QString CustomMode::INTERVAL_1_TIME = "Interval1Time";
+const QString CustomMode::INTERVAL_2_TIME = "Interval2Time";
+const QString CustomMode::INTERVAL_REPETITIONS = "IntervalRepetitions";
+const QString CustomMode::ACTIVITY_NAME = "Name";
+const QString CustomMode::RECORDING_INTERVAL = "RecordingInterval";
+const QString CustomMode::USE_ACCELEROMETER = "UseAccelerometer";
+const QString CustomMode::USE_AUTOLAP = "UseAutolap";
+const QString CustomMode::USE_BIKE_POD = "UseBikePOD";
+const QString CustomMode::USE_CADENS_POD = "UseCadencePOD";
+const QString CustomMode::USE_FOOT_POD = "UseFootPOD";
+const QString CustomMode::USE_POWER_POD = "UsePowerPOD";
+const QString CustomMode::USE_HR_BELT = "UseHRBelt";
+const QString CustomMode::USE_HR_LIMITS = "UseHRLimits";
+const QString CustomMode::USE_INTERVALS = "UseIntervals";
+const QString CustomMode::SPORT_MODE_ID = "CustomModeID";
+const QString CustomMode::AUTO_SCROLING_SPEED = "AutoScrolling";
+const QString CustomMode::AUTO_PAUSE_SPEED = "AutoPauseSpeed";
+const QString CustomMode::BACKLIGHT_MODE = "BacklightMode";
+const QString CustomMode::DISPLAY_IS_NEGATIVE = "DisplayIsNegative";
+const QString CustomMode::SHOW_NAVIGATION_SELECTION = "ShowNavigationSelection";
+const QString CustomMode::DISPLAY = "Displays";
+const QString CustomMode::DISPLAYED_RULE_IDS = "DisplayedRuleIDs";
+const QString CustomMode::LOGGED_RULE_IDS = "LoggedRuleIDs";
+
+
+CustomMode::CustomMode(QVariantMap &customModeMap, QObject *parent) :
+    QObject(parent)
+{
+    activityId = customModeMap[ACTIVITY_ID].toUInt();
+    altiBaroMode = customModeMap[ALTI_BARO_MODE].toUInt();
+    autolapDistance = customModeMap[AUTOLAP_DISTANCE].toUInt();
+    gpsInterval = customModeMap[GPS_INTERVAL].toUInt();
+    hrLimitHigh = customModeMap[HR_LIMIT_HIGH].toUInt();
+    hrLimitLow = customModeMap[HR_LIMIT_LOW].toUInt();
+    interval1distance = customModeMap[INTERVAL_1_DISTANCE].toUInt();
+    interval2distance = customModeMap[INTERVAL_2_DISTANCE].toUInt();
+    interval1time = customModeMap[INTERVAL_1_TIME].toUInt();
+    interval2time = customModeMap[INTERVAL_2_TIME].toUInt();
+    intervalRepetitions = customModeMap[INTERVAL_REPETITIONS].toUInt();
+    activityName = customModeMap[ACTIVITY_NAME].toString();
+    recordingInterval = customModeMap[RECORDING_INTERVAL].toUInt();
+    useAccelerometer = customModeMap[USE_ACCELEROMETER].toBool();
+    useAutolap = customModeMap[USE_AUTOLAP].toBool();
+    useBikePod = customModeMap[USE_BIKE_POD].toBool();
+    useCadencePod = customModeMap[USE_CADENS_POD].toBool();
+    useFootPod = customModeMap[USE_FOOT_POD].toBool();
+    usePowerPod = customModeMap[USE_POWER_POD].toBool();
+    useHrBelt = customModeMap[USE_HR_BELT].toBool();
+    useHrLimits = customModeMap[USE_HR_LIMITS].toBool();
+    useIntervals = customModeMap[USE_INTERVALS].toBool();
+    sportmodeId = customModeMap[SPORT_MODE_ID].toUInt();
+    if (customModeMap[AUTO_SCROLING_SPEED].toString() == QString::null) {
+        autoScrolingSpeed = 0;
+    }
+    else {
+        autoScrolingSpeed = customModeMap[AUTO_SCROLING_SPEED].toUInt();
+    }
+    autoPauseSpeed = customModeMap[AUTO_PAUSE_SPEED].toFloat();
+    if (customModeMap[BACKLIGHT_MODE].toString() == QString::null) {
+        backlightMode = 0xff;
+    }
+    else {
+        backlightMode = customModeMap[BACKLIGHT_MODE].toUInt();
+    }
+    if (customModeMap[DISPLAY_IS_NEGATIVE].toString() == QString::null) {
+        displayIsNegative = 0xff;
+    }
+    else {
+        displayIsNegative = customModeMap[DISPLAY_IS_NEGATIVE].toUInt();
+    }
+    showNavigationSelection = customModeMap[SHOW_NAVIGATION_SELECTION].toUInt();
+
+    foreach (QVariant displayVar, customModeMap[DISPLAY].toList()) {
+        QVariantMap displayMap = displayVar.toMap();
+
+        CustomModeDisplay display(displayMap, this->parent());
+        displays.append(display);
+    }
+
+    foreach (QVariant ruleIdsVar, customModeMap[DISPLAYED_RULE_IDS].toList()) {
+        int ruleId = ruleIdsVar.toInt();
+        appRuleIds.append(ruleId);
+    }
+
+    foreach (QVariant loggedRuleIdsVar, customModeMap[LOGGED_RULE_IDS].toList()) {
+        int ruleId = loggedRuleIdsVar.toInt();
+        loggedAppRuleIds.append(ruleId);
+    }
+}
+
+CustomMode::CustomMode(const CustomMode &other) :
+    QObject(other.parent()),
+    activityId(other.activityId),
+    altiBaroMode(other.altiBaroMode),
+    autolapDistance(other.autolapDistance),
+    gpsInterval(other.gpsInterval),
+    hrLimitHigh(other.hrLimitHigh),
+    hrLimitLow(other.hrLimitLow),
+    interval1distance(other.interval1distance),
+    interval2distance(other.interval2distance),
+    interval1time(other.interval1time),
+    interval2time(other.interval2time),
+    intervalRepetitions(other.intervalRepetitions),
+    activityName(other.activityName),
+    recordingInterval(other.recordingInterval),
+    useAccelerometer(other.useAccelerometer),
+    useAutolap(other.useAutolap),
+    useBikePod(other.useBikePod),
+    useCadencePod(other.useCadencePod),
+    useFootPod(other.useFootPod),
+    usePowerPod(other.usePowerPod),
+    useHrBelt(other.useHrBelt),
+    useHrLimits(other.useHrLimits),
+    useIntervals(other.useIntervals),
+    sportmodeId(other.sportmodeId),
+    autoScrolingSpeed(other.autoScrolingSpeed),
+    autoPauseSpeed(other.autoPauseSpeed),
+    backlightMode(other.backlightMode),
+    displayIsNegative(other.displayIsNegative),
+    showNavigationSelection(other.showNavigationSelection),
+    displays(other.displays),
+    appRuleIds(other.appRuleIds),
+    loggedAppRuleIds(other.loggedAppRuleIds)
+{
+}
+
+CustomMode &CustomMode::operator=(const CustomMode &rhs)
+{
+    activityId = rhs.activityId;
+    altiBaroMode = rhs.altiBaroMode;
+    autolapDistance = rhs.autolapDistance;
+    gpsInterval = rhs.gpsInterval;
+    hrLimitHigh = rhs.hrLimitHigh;
+    hrLimitLow = rhs.hrLimitLow;
+    interval1distance = rhs.interval1distance;
+    interval2distance = rhs.interval2distance;
+    interval1time = rhs.interval1time;
+    interval2time = rhs.interval2time;
+    intervalRepetitions = rhs.intervalRepetitions;
+    activityName = rhs.activityName;
+    recordingInterval = rhs.recordingInterval;
+    useAccelerometer = rhs.useAccelerometer;
+    useAutolap = rhs.useAutolap;
+    useBikePod = rhs.useBikePod;
+    useCadencePod = rhs.useCadencePod;
+    useFootPod = rhs.useFootPod;
+    usePowerPod = rhs.usePowerPod;
+    useHrBelt = rhs.useHrBelt;
+    useHrLimits = rhs.useHrLimits;
+    useIntervals = rhs.useIntervals;
+    sportmodeId = rhs.sportmodeId;
+    autoScrolingSpeed = rhs.autoScrolingSpeed;
+    autoPauseSpeed = rhs.autoPauseSpeed;
+    backlightMode = rhs.backlightMode;
+    displayIsNegative = rhs.displayIsNegative;
+    showNavigationSelection = rhs.showNavigationSelection;
+    displays = rhs.displays;
+    appRuleIds = rhs.appRuleIds;
+    loggedAppRuleIds = rhs.loggedAppRuleIds;
+
+    return *this;
+}
+
+void CustomMode::toAmbitCustomModeData(ambit_sport_mode_t *ambitCustomMode, ambit_sport_mode_device_settings_t *ambitSettings)
+{
+    // Copy settings
+    ambit_sport_mode_settings_t *ambitCustomModeSettings = &(ambitCustomMode->settings);
+    toAmbitSettings(ambitCustomModeSettings);
+
+    // Copy displays
+    if (libambit_malloc_sport_mode_displays(displays.count(), ambitCustomMode)) {
+        ambit_sport_mode_display_t *ambitDisplays = ambitCustomMode->display;
+
+        foreach (CustomModeDisplay display, displays) {
+            display.toAmbitCustomModeData(ambitDisplays);
+            ambitDisplays++;
+        }
+    }
+
+    if (libambit_malloc_sport_mode_app_ids(appRuleIds.count(), ambitCustomMode)) {
+        for(int i = 0; i < appRuleIds.count(); i++) {
+            ambitCustomMode->apps_list[i].index = ambitSettings->app_ids_count;
+            ambitCustomMode->apps_list[i].logging = (loggedAppRuleIds.at(i) != 0);
+
+            ambitSettings->app_ids[ambitSettings->app_ids_count] = appRuleIds.at(i);
+            ambitSettings->app_ids_count++;
+        }
+    }
+}
+
+void CustomMode::toAmbitSettings(ambit_sport_mode_settings_t *settings)
+{
+    toAmbitName(settings->activity_name);
+    settings->activity_id = (uint16_t)activityId;
+    settings->sport_mode_id = (uint16_t)sportmodeId;
+    memset(settings->unknown1, 0, sizeof(settings->unknown1));
+    settings->hrbelt_and_pods = hrbeltAndPods();
+    settings->alti_baro_mode = altiBaroMode;
+    settings->gps_interval = gpsInterval;
+    settings->recording_interval = recordingInterval;
+    settings->autolap = useAutolap ? autolapDistance : 0;
+    settings->heartrate_max = hrLimitHigh;
+    settings->heartrate_min = hrLimitLow;
+    settings->use_heartrate_limits = useHrLimits;
+    memset(settings->unknown2, 0, sizeof(settings->unknown2));
+    settings->auto_pause = autoPauseSpeed * 100;
+    settings->auto_scroll = autoScrolingSpeed;
+    settings->use_interval_timer = useIntervals ? 1 : 0;
+    settings->interval_repetitions = intervalRepetitions;
+    settings->interval_timer_max_unit = interval1time ? 0x0100 : 0;
+    memset(settings->unknown3, 0, sizeof(settings->unknown3));
+    settings->interval_timer_max = interval1distance ? interval1distance : interval1time;
+    memset(settings->unknown4, 0, sizeof(settings->unknown4));
+    settings->interval_timer_min_unit = interval2time ? 0x0100 : 0;
+    memset(settings->unknown5, 0, sizeof(settings->unknown5));
+    settings->interval_timer_min = interval2distance ? interval2distance : interval2time;
+    memset(settings->unknown6, 0, sizeof(settings->unknown6));
+    settings->backlight_mode = backlightMode;
+    settings->display_mode = displayIsNegative;
+    settings->quick_navigation = showNavigationSelection;
+}
+
+void CustomMode::toAmbitName(char ambitName[NAME_SIZE])
+{
+    const char *source = activityName.toStdString().c_str();
+    int strLen = activityName.length() < NAME_SIZE ? activityName.length() : NAME_SIZE;
+    memset(ambitName, 0x00, NAME_SIZE);
+    memcpy(ambitName, source, strLen);
+}
+
+u_int16_t CustomMode::hrbeltAndPods()
+{
+    u_int16_t retVal = 0;
+
+    if (useHrBelt)          { retVal |= 0x0003; }
+    if (useAccelerometer)   { retVal |= 0x0004; }
+    if (usePowerPod)        { retVal |= 0x0042; }
+    if (useCadencePod)      { retVal |= 0x0082; }
+    if (useFootPod)         { retVal |= 0x0102; }
+    if (useBikePod)         { retVal |= 0x0802; }
+
+    return retVal;
+}
+
+uint CustomMode::getCustomModeId() const
+{
+    return sportmodeId;
+}
+
+const QString CustomModeDisplay::REQUIRES_HR_BELT = "RequiresHRBelt";
+const QString CustomModeDisplay::ROW_1 = "Row1";
+const QString CustomModeDisplay::ROW_2 = "Row2";
+const QString CustomModeDisplay::TYPE = "Type";
+const QString CustomModeDisplay::VIEWS = "Views";
+
+CustomModeDisplay::CustomModeDisplay(QVariantMap &displayMap, QObject *parent) :
+    QObject(parent)
+{
+    bool ok = false;
+    requiresHRBelt = displayMap[REQUIRES_HR_BELT].toBool();
+    row1 = displayMap[ROW_1].toInt(&ok);
+    if (!ok) {
+        row1 = -1;
+    }
+    row2 = displayMap[ROW_2].toInt(&ok);
+    if (!ok) {
+        row2 = -1;
+    }
+    type = displayMap[TYPE].toInt();
+
+    foreach (QVariant viewVar, displayMap[VIEWS].toList()) {
+        int view = viewVar.toInt();
+        views.append(view);
+    }
+}
+
+CustomModeDisplay::CustomModeDisplay(const CustomModeDisplay &other) :
+    QObject(other.parent()),
+    requiresHRBelt(other.requiresHRBelt),
+    row1(other.row1),
+    row2(other.row2),
+    type(other.type),
+    views(other.views)
+{
+}
+
+CustomModeDisplay &CustomModeDisplay::operator=(const CustomModeDisplay &rhs)
+{
+    requiresHRBelt = rhs.requiresHRBelt;
+    row1 = rhs.row1;
+    row2 = rhs.row2;
+    type = rhs.type;
+    views = rhs.views;
+
+    return *this;
+}
+
+void CustomModeDisplay::toAmbitCustomModeData(ambit_sport_mode_display_t *ambitDisplay)
+{
+    ambitDisplay->type = ambitDisplayType();
+    ambitDisplay->requiresHRBelt = requiresHRBelt;
+
+    if (type == MOVESCOUNT_BAROGRAPH_DISPLAY_TYPE) {
+        toAmbitBarographDisplay(ambitDisplay);
+    }
+    else if (type == MOVESCOUNT_LINEGRAPH_DISPLAY_TYPE) {
+        toAmbitLinegraphDisplay(ambitDisplay);
+    }
+    else {
+        toAmbitTextDisplay(ambitDisplay);
+    }
+}
+
+void CustomModeDisplay::toAmbitBarographDisplay(ambit_sport_mode_display_t *ambitDisplay)
+{
+    ambitDisplay->row1 = 0x07;  // pressure
+    ambitDisplay->row2 = 0x0e;
+    ambitDisplay->row3 = 0x00;
+
+    libambit_malloc_sport_mode_view(3, ambitDisplay);
+    ambitDisplay->view[0] = 0x0d;   // Temperature
+    ambitDisplay->view[1] = 0x01;   // Day time
+    ambitDisplay->view[2] = 0x12;   // Ref hight
+}
+
+void CustomModeDisplay::toAmbitLinegraphDisplay(ambit_sport_mode_display_t *ambitDisplay)
+{
+    ambitDisplay->row1 = movescount2ambitConverter.value(row1);
+    switch (row1) {
+    case 0:
+        ambitDisplay->row2 = 0x20;
+        break;
+    case 11:
+        ambitDisplay->row2 = 0x16;
+        break;
+    default:
+        ambitDisplay->row2 = 0x6d;
+        break;
+    }
+
+    ambitDisplay->row3 = 0x05; // Chrono
+}
+
+void CustomModeDisplay::toAmbitTextDisplay(ambit_sport_mode_display_t *ambitDisplay)
+{
+    ambitDisplay->row1 = movescount2ambitConverter.value(row1);
+    ambitDisplay->row2 = movescount2ambitConverter.value(row2);
+    ambitDisplay->row3 = 0;
+
+    if (libambit_malloc_sport_mode_view(views.count(), ambitDisplay)) {
+        uint16_t *ambitViews = ambitDisplay->view;
+
+        foreach (int view, views) {
+            *ambitViews = movescount2ambitConverter.value(view);
+            ambitViews++;
+        }
+    }
+}
+
+u_int16_t CustomModeDisplay::ambitDisplayType()
+{
+    switch (type) {
+    case MOVESCOUNT_TRIPLE_ROW_DISPLAY_TYPE:
+        return AMBIT_TRIPLE_ROW_DISPLAY_TYPE;
+        break;
+    case MOVESCOUNT_DOUBLE_ROWS_DISPLAY_TYPE:
+        return AMBIT_DOUBLE_ROWS_DISPLAY_TYPE;
+        break;
+    case MOVESCOUNT_BAROGRAPH_DISPLAY_TYPE:
+        return AMBIT_GRAPH_DISPLAY_TYPE;
+        break;
+    case MOVESCOUNT_LINEGRAPH_DISPLAY_TYPE:
+        return AMBIT_GRAPH_DISPLAY_TYPE;
+        break;
+    case MOVESCOUNT_SINGLE_ROW_DISPLAY_TYPE:
+        return AMBIT_SINGLE_ROW_DISPLAY_TYPE;
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+QMap<int, int> qmapInit() {
+    QMap<int, int> map;
+    map.insert(17, 0xb);    // Speed
+    map.insert(3, 0xc);
+    map.insert(15, 0x31);
+    map.insert(16, 0x1c);   // Pace
+    map.insert(25, 0x1d);
+    map.insert(4, 0x7);
+    map.insert(7, 0x5);     // Chrono
+    map.insert(10, 0x1b);
+    map.insert(19, 0xd);    // Temperature
+    map.insert(20, 0x1);    // Day time
+    map.insert(31, 0x30);   // Lap avg pace
+    map.insert(12, 0x2d);
+    map.insert(13, 0x2e);   // Lap time
+    map.insert(23, 0xfffe);
+    map.insert(32, 0x44);   // Battery charge
+    map.insert(60, 0x43);
+    map.insert(8, 0xa);     // Distance
+    map.insert(14, 0x2f);   // Lap distance
+    map.insert(61, 0x4a);
+    map.insert(62, 0x4b);
+    map.insert(63, 0x4c);
+    map.insert(64, 0x4d);
+    map.insert(65, 0x4e);
+    map.insert(66, 0x4f);
+    map.insert(67, 0x50);
+    map.insert(11, 0x15);   // Heart beat
+    map.insert(2, 0x9);     // Average heart rate
+    map.insert(5, 0x17);
+    map.insert(21, 0x1f);   // Peak Training Effect
+    map.insert(6, 0x11);    // Calories
+    map.insert(0, 0x6);     // Altitude
+    map.insert(1, 0x21);
+    map.insert(9, 0x22);
+    map.insert(22, 0x2c);
+    map.insert(33, 0x46);   // Current activity duration
+    map.insert(34, 0x47);
+    map.insert(35, 0x48);
+    map.insert(36, 0x49);
+    map.insert(100,0x33); // App index
+    map.insert(101,0x34); // App index
+    map.insert(102,0x35); // App index
+    map.insert(103,0x6b); // App index
+    map.insert(104,0x6c); // App index
+    map.insert(-1, 0x0);
+
+    return map;
+}
diff --git a/src/movescount/sportmode.h b/src/movescount/sportmode.h
new file mode 100644
index 0000000..0102558
--- /dev/null
+++ b/src/movescount/sportmode.h
@@ -0,0 +1,149 @@
+#ifndef CUSTOMMODE_H
+#define CUSTOMMODE_H
+
+#include <QObject>
+#include <QVariantMap>
+#include <QMap>
+#include <QList>
+
+#include "libambit.h"
+
+QMap<int, int> qmapInit();
+static const QMap<int, int> movescount2ambitConverter = qmapInit();
+
+class CustomModeDisplay : public QObject
+{
+    Q_OBJECT
+public:
+    explicit CustomModeDisplay(QVariantMap &displayMap, QObject *parent = 0);
+    CustomModeDisplay(const CustomModeDisplay &other);
+
+    CustomModeDisplay& operator=(const CustomModeDisplay &rhs);
+
+    void toAmbitCustomModeData(ambit_sport_mode_display_t *ambitDisplay);
+
+private:
+    u_int16_t ambitDisplayType();
+    void toAmbitBarographDisplay(ambit_sport_mode_display_t *ambitDisplay);
+    void toAmbitLinegraphDisplay(ambit_sport_mode_display_t *ambitDisplay);
+    void toAmbitTextDisplay(ambit_sport_mode_display_t *ambitDisplay);
+
+    bool requiresHRBelt;
+    int row1;
+    int row2;
+    int type;
+    QList<int> views;
+
+
+    static const QString REQUIRES_HR_BELT;
+    static const QString ROW_1;
+    static const QString ROW_2;
+    static const QString TYPE;
+    static const QString VIEWS;
+
+    static const int AMBIT_SINGLE_ROW_DISPLAY_TYPE = 0x0106;
+    static const int AMBIT_DOUBLE_ROWS_DISPLAY_TYPE = 0x0105;
+    static const int AMBIT_TRIPLE_ROW_DISPLAY_TYPE = 0x0104;
+    static const int AMBIT_GRAPH_DISPLAY_TYPE = 0x0101;
+
+    static const int MOVESCOUNT_SINGLE_ROW_DISPLAY_TYPE = 4;
+    static const int MOVESCOUNT_DOUBLE_ROWS_DISPLAY_TYPE = 6;
+    static const int MOVESCOUNT_TRIPLE_ROW_DISPLAY_TYPE = 5;
+    static const int MOVESCOUNT_LINEGRAPH_DISPLAY_TYPE = 1;
+    static const int MOVESCOUNT_BAROGRAPH_DISPLAY_TYPE = 8;
+};
+
+class CustomMode : public QObject
+{
+    Q_OBJECT
+public:
+    explicit CustomMode(QVariantMap &customModeMap, QObject *parent = 0);
+    CustomMode(const CustomMode &other);
+
+    CustomMode& operator=(const CustomMode &rhs);
+
+    uint getCustomModeId() const;
+
+    void toAmbitCustomModeData(ambit_sport_mode_t *ambitCustomMode, ambit_sport_mode_device_settings_t *ambitSettings);
+    void toAmbitSettings(ambit_sport_mode_settings_t *settings);
+    void toAmbitName(char ambitName[]);
+
+signals:
+
+public slots:
+
+private:
+    u_int16_t hrbeltAndPods();
+
+    uint activityId;
+    uint altiBaroMode;
+//    uint autoPause;
+    uint autolapDistance;
+    uint gpsInterval;
+    uint hrLimitHigh;
+    uint hrLimitLow;
+    uint interval1distance;
+    uint interval2distance;
+    uint interval1time;
+    uint interval2time;
+    uint intervalRepetitions;
+    QString activityName;
+    uint recordingInterval;
+//    uint tonesMode;
+    bool useAccelerometer;
+    bool useAutolap;
+//    bool useAutomaticLogRecording;
+    bool useBikePod;
+    bool useCadencePod;
+    bool useFootPod;
+    bool usePowerPod;
+    bool useHrBelt;
+    bool useHrLimits;
+    bool useIntervals;
+    uint sportmodeId;
+    uint autoScrolingSpeed;
+    float autoPauseSpeed;
+    uint backlightMode;
+    uint displayIsNegative;
+    uint showNavigationSelection;
+    QList<CustomModeDisplay> displays;
+    QList<uint> appRuleIds;
+    QList<uint> loggedAppRuleIds;
+
+public:
+    static const QString ACTIVITY_ID;
+    static const QString ALTI_BARO_MODE;
+    static const QString AUTOLAP_DISTANCE;
+    static const QString GPS_INTERVAL;
+    static const QString HR_LIMIT_HIGH;
+    static const QString HR_LIMIT_LOW;
+    static const QString INTERVAL_1_DISTANCE;
+    static const QString INTERVAL_2_DISTANCE;
+    static const QString INTERVAL_1_TIME;
+    static const QString INTERVAL_2_TIME;
+    static const QString INTERVAL_REPETITIONS;
+    static const QString ACTIVITY_NAME;
+    static const QString RECORDING_INTERVAL;
+    static const QString USE_ACCELEROMETER;
+    static const QString USE_AUTOLAP;
+    static const QString USE_BIKE_POD;
+    static const QString USE_CADENS_POD;
+    static const QString USE_FOOT_POD;
+    static const QString USE_POWER_POD;
+    static const QString USE_HR_BELT;
+    static const QString USE_HR_LIMITS;
+    static const QString USE_INTERVALS;
+    static const QString SPORT_MODE_ID;
+    static const QString AUTO_SCROLING_SPEED;
+    static const QString AUTO_PAUSE_SPEED;
+    static const QString BACKLIGHT_MODE;
+    static const QString DISPLAY_IS_NEGATIVE;
+    static const QString SHOW_NAVIGATION_SELECTION;
+    static const QString DISPLAY;
+    static const QString DISPLAYED_RULE_IDS;
+    static const QString LOGGED_RULE_IDS;
+
+    static const int NAME_SIZE = 16;
+};
+
+#endif // CUSTOMMODE_H
diff --git a/src/movescount/sportmodegroup.cpp b/src/movescount/sportmodegroup.cpp
new file mode 100644
index 0000000..67cc7a7
--- /dev/null
+++ b/src/movescount/sportmodegroup.cpp
@@ -0,0 +1,77 @@
+#include "sportmodegroup.h"
+#include "libambit.h"
+
+const QString CustomModeGroup::ACTIVITY_ID = "ActivityID";
+const QString CustomModeGroup::SPORT_MODE_GROUPS_ID = "CustomModeGroupsID";
+const QString CustomModeGroup::SPORT_MODE_IDS = "CustomModeIDs";
+const QString CustomModeGroup::IS_VISIBLE = "IsVisible";
+const QString CustomModeGroup::ACTIVITY_NAME = "Name";
+
+CustomModeGroup::CustomModeGroup(QVariantMap &customModeGroupMap, QObject *parent) :
+    QObject(parent)
+{
+    activityId = customModeGroupMap[ACTIVITY_ID].toUInt();
+    customModeGroupsId = customModeGroupMap[SPORT_MODE_GROUPS_ID].toInt();
+    isVisible = customModeGroupMap[IS_VISIBLE].toBool();
+    activityName = customModeGroupMap[ACTIVITY_NAME].toString();
+
+    foreach (QVariant customModeIdVar, customModeGroupMap[SPORT_MODE_IDS].toList()) {
+        customModeIds.append(customModeIdVar.toInt());
+    }
+}
+
+CustomModeGroup::CustomModeGroup(const CustomModeGroup &other) :
+    QObject(other.parent()),
+    activityId(other.activityId),
+    customModeGroupsId(other.customModeGroupsId),
+    customModeIds(other.customModeIds),
+    isVisible(other.isVisible),
+    activityName(other.activityName),
+    customModeIndex(other.customModeIndex)
+{
+}
+
+CustomModeGroup &CustomModeGroup::operator=(const CustomModeGroup &rhs)
+{
+    activityId = rhs.activityId;
+    customModeGroupsId = rhs.customModeGroupsId;
+    customModeIds = rhs.customModeIds;
+    isVisible = rhs.isVisible;
+    activityName = rhs.activityName;
+    customModeIndex = rhs.customModeIndex;
+
+    return *this;
+}
+
+void CustomModeGroup::setCustomModeIndex(const QList<u_int16_t> &customModesList)
+{
+    foreach (int customModeId, customModeIds) {
+        customModeIndex.append(customModesList.indexOf(customModeId));
+    }
+}
+
+void CustomModeGroup::toAmbitData(ambit_sport_mode_group_t *ambitCustomModeGroups)
+{
+    ambitCustomModeGroups->activity_id = activityId;
+    ambitCustomModeGroups->sport_mode_group_id = customModeGroupsId;
+    ambitCustomModeGroups->is_visible = isVisible;
+    toAmbitName(ambitCustomModeGroups->activity_name);
+
+    if (libambit_malloc_sport_mode_index(customModeIndex.count(), ambitCustomModeGroups)) {
+        uint16_t *ambitCustomModeIndex = ambitCustomModeGroups->sport_mode_index;
+
+        foreach (u_int16_t index, customModeIndex) {
+            // Write the IDs/position/index for all the custom mode that is in this group.
+            *ambitCustomModeIndex = index;
+            ambitCustomModeIndex++;
+        }
+    }
+}
+
+void CustomModeGroup::toAmbitName(char ambitName[GROUP_NAME_SIZE])
+{
+    const char *source = activityName.toStdString().c_str();
+    int strLen = activityName.length() < GROUP_NAME_SIZE ? activityName.length() : GROUP_NAME_SIZE;
+    memset(ambitName, 0x00, GROUP_NAME_SIZE);
+    memcpy(ambitName, source, strLen);
+}
diff --git a/src/movescount/sportmodegroup.h b/src/movescount/sportmodegroup.h
new file mode 100644
index 0000000..d81d250
--- /dev/null
+++ b/src/movescount/sportmodegroup.h
@@ -0,0 +1,46 @@
+#ifndef CUSTOMMODEGROUP_H
+#define CUSTOMMODEGROUP_H
+
+#include <QObject>
+#include <QVariantMap>
+#include <QList>
+#include "libambit.h"
+
+class CustomModeGroup : public QObject
+{
+    Q_OBJECT
+public:
+    explicit CustomModeGroup(QVariantMap &customModeGroupMap, QObject *parent = 0);
+    CustomModeGroup(const CustomModeGroup &other);
+
+    CustomModeGroup& operator=(const CustomModeGroup &rhs);
+
+    void setCustomModeIndex(const QList<u_int16_t> &customModesList);
+
+    void toAmbitData(ambit_sport_mode_group_t *ambitCustomModeGroups);
+
+signals:
+
+public slots:
+
+private:
+    void toAmbitName(char ambitName[]);
+
+    int activityId;
+    int customModeGroupsId;
+    QList<int> customModeIds;
+    bool isVisible;
+    QString activityName;
+
+    QList<uint> customModeIndex;
+
+    static const QString ACTIVITY_ID;
+    static const QString SPORT_MODE_GROUPS_ID;
+    static const QString SPORT_MODE_IDS;
+    static const QString IS_VISIBLE;
+    static const QString ACTIVITY_NAME;
+
+    static const int GROUP_NAME_SIZE = 24;
+};
+
+#endif // CUSTOMMODEGROUP_H
diff --git a/src/openambit/CMakeLists.txt b/src/openambit/CMakeLists.txt
index 1e654aa..2f8a086 100644
--- a/src/openambit/CMakeLists.txt
+++ b/src/openambit/CMakeLists.txt
@@ -1,26 +1,28 @@
 cmake_minimum_required(VERSION 2.8.5)
 project (OPENAMBIT CXX)
 
-set (OPENAMBIT_VERSION HEAD)
+set (OPENAMBIT_VERSION 0.4)
 
 # Where to lookup modules
 set(CMAKE_MODULE_PATH "${OPENAMBIT_SOURCE_DIR}/cmake")
 
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
 
-find_package(Qt4 REQUIRED)
+if(USE_QT5)
+  find_package(Qt5Widgets REQUIRED)
+  find_package(Qt5LinguistTools REQUIRED)
+else(USE_QT5)
+  find_package(Qt4 REQUIRED)
+endif(USE_QT5)
 find_package(libambit REQUIRED)
 find_package(Movescount REQUIRED)
 find_package(UDev REQUIRED)
 
-include(${QT_USE_FILE})
 include(GNUInstallDirs)
 
-include_directories (
-  ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
-  ${QT_QTCORE_INCLUDE_DIR}
-  ${QT_QTGUI_INCLUDE_DIR}
-  ${QT_QTNETWORK_INCLUDE_DIR}
+include_directories(
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  ${CMAKE_CURRENT_BINARY_DIR}
   ${LIBAMBIT_INCLUDE_DIR}
   ..
 )
@@ -30,7 +32,19 @@ link_directories(
   ${MOVESCOUNT_LIBS_DIR}
 )
 
-set ( openambit_SRCS
+set(openambit_HDRS
+  confirmbetadialog.h
+  devicemanager.h
+  logview.h
+  mainwindow.h
+  settings.h
+  settingsdialog.h
+  signalhandler.h
+  single_application.h
+  udevlistener.h
+)
+
+set(openambit_SRCS
   confirmbetadialog.cpp
   devicemanager.cpp
   logview.cpp
@@ -43,41 +57,37 @@ set ( openambit_SRCS
   udevlistener.cpp
 )
 
-set ( openambit_UIS
+set(openambit_UIS
   confirmbetadialog.ui
   mainwindow.ui
   settingsdialog.ui
 )
 
-set ( openambit_RSCS
+set(openambit_RSCS
   resources.qrc
 )
 
-set ( openambit_MOCS
-  confirmbetadialog.h
-  devicemanager.h
-  logview.h
-  mainwindow.h
-  settings.h
-  settingsdialog.h
-  signalhandler.h
-  single_application.h
-  udevlistener.h
-)
-
-set (FILES_TO_TRANSLATE ${openambit_SRCS} ${openambit_UIS} ${openambit_MOCS})
+set(FILES_TO_TRANSLATE ${openambit_SRCS} ${openambit_UIS} ${openambit_MOCS})
 
-set ( APP_ICON ${PROJECT_SOURCE_DIR}/icons/icon_disconnected.png )
+set(APP_ICON ${PROJECT_SOURCE_DIR}/icons/icon_disconnected.png)
 
 ######### Translations
-file (GLOB TRANSLATIONS_FILES translations/*.ts)
-
-option (UPDATE_TRANSLATIONS "Update source translation translations/*.ts")
-if (UPDATE_TRANSLATIONS)
-  qt4_create_translation(QM_FILES ${FILES_TO_TRANSLATE} ${TRANSLATIONS_FILES})
-else (UPDATE_TRANSLATIONS)
-  qt4_add_translation(QM_FILES ${TRANSLATIONS_FILES})
-endif (UPDATE_TRANSLATIONS)
+file(GLOB TRANSLATIONS_FILES translations/*.ts)
+
+option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts")
+if(USE_QT5)
+  if(UPDATE_TRANSLATIONS)
+    qt5_create_translation(QM_FILES ${FILES_TO_TRANSLATE} ${TRANSLATIONS_FILES})
+  else(UPDATE_TRANSLATIONS)
+    qt5_add_translation(QM_FILES ${TRANSLATIONS_FILES})
+  endif(UPDATE_TRANSLATIONS)
+else(USE_QT5)
+  if(UPDATE_TRANSLATIONS)
+    qt4_create_translation(QM_FILES ${FILES_TO_TRANSLATE} ${TRANSLATIONS_FILES})
+  else(UPDATE_TRANSLATIONS)
+    qt4_add_translation(QM_FILES ${TRANSLATIONS_FILES})
+  endif(UPDATE_TRANSLATIONS)
+endif(USE_QT5)
 
 # Create translations QRC file - ts.qrc
 set(TRANSLATIONS_QRC "${CMAKE_CURRENT_BINARY_DIR}/ts.qrc")
@@ -91,23 +101,35 @@ list(APPEND openambit_RSCS ${TRANSLATIONS_QRC})
 
 # prevent the generated files from being deleted during make clean
 set_directory_properties(PROPERTIES CLEAN_NO_CUSTOM true)
-
 ######### Translations
 
-QT4_WRAP_UI(UIS ${openambit_UIS})
-QT4_ADD_RESOURCES(RSCS ${openambit_RSCS})
-QT4_WRAP_CPP(MOCS ${openambit_MOCS})
+if(USE_QT5)
+  QT5_WRAP_UI(UIS ${openambit_UIS})
+  QT5_ADD_RESOURCES(RSCS ${openambit_RSCS})
+else(USE_QT5)
+  QT4_WRAP_UI(UIS ${openambit_UIS})
+  QT4_ADD_RESOURCES(RSCS ${openambit_RSCS})
+endif(USE_QT5)
+
+set(CMAKE_AUTOMOC ON)
 
-add_definitions( -DAPP_VERSION="${OPENAMBIT_VERSION}" )
+add_definitions(-DAPP_VERSION="${OPENAMBIT_VERSION}")
 
-add_executable ( openambit ${openambit_SRCS} ${UIS} ${RSCS} ${MOCS} )
+add_executable(openambit ${openambit_HDRS} ${openambit_SRCS} ${UIS} ${RSCS})
 
-target_link_libraries ( openambit  ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTNETWORK_LIBRARY} ${LIBAMBIT_LIBS} ${MOVESCOUNT_LIBS} ${UDEV_LIBS} )
+if(USE_QT5)
+  QT5_USE_MODULES(openambit Core Widgets Network)
+else(USE_QT5)
+  QT4_USE_MODULES(openambit Core Gui Network)
+endif(USE_QT5)
 
-install ( TARGETS openambit DESTINATION ${CMAKE_INSTALL_BINDIR} )
-install ( FILES ${OPENAMBIT_SOURCE_DIR}/deployment/openambit.desktop
-          DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications )
-install ( FILES ${APP_ICON}
-          DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps
-          RENAME openambit.png )
+target_link_libraries(openambit ${LIBAMBIT_LIBS} ${MOVESCOUNT_LIBS} ${UDEV_LIBS} )
 
+install(TARGETS openambit DESTINATION ${CMAKE_INSTALL_BINDIR})
+install(FILES ${OPENAMBIT_SOURCE_DIR}/deployment/openambit.desktop
+        DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
+install(FILES ${OPENAMBIT_SOURCE_DIR}/deployment/openambit.appdata.xml
+        DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/appdata )
+install(FILES ${APP_ICON}
+        DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps
+        RENAME openambit.png)
diff --git a/src/openambit/deployment/openambit.appdata.xml b/src/openambit/deployment/openambit.appdata.xml
new file mode 100644
index 0000000..2422944
--- /dev/null
+++ b/src/openambit/deployment/openambit.appdata.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application>
+	<id type="desktop">openambit.desktop</id>
+	<metadata_license>CC0-1.0</metadata_license>
+	<project_license>GPL-3.0+</project_license>
+	<name>Openambit</name>
+	<summary>Open software for the Suunto Ambit(2)</summary>
+	<description>
+		<p>
+			Openambit is application for downloading moves from the Suunto
+			Ambit(2) outdoor watches, and synchronizing them with the
+			movescount website.
+		</p>
+		<p>
+			OpenAmbit an open source alternative to Moveslink application from Suunto.
+		</p>
+	</description>
+	<screenshots>
+		<screenshot type="default">
+			<image>http://openambit.org/wp-content/uploads/2014/03/openambit-screenshot.png</image>
+		</screenshot>
+	</screenshots>
+	<url type="homepage">http://openambit.org/</url>
+	<updatecontact>manisandro at gmail.com</updatecontact>
+</application>
diff --git a/src/openambit/devicemanager.cpp b/src/openambit/devicemanager.cpp
index ee4f04a..bc36b68 100644
--- a/src/openambit/devicemanager.cpp
+++ b/src/openambit/devicemanager.cpp
@@ -22,12 +22,15 @@
 #include "devicemanager.h"
 
 #include <QTimer>
+#include <QDebug>
+#include <stdio.h>
 #include <libambit.h>
 
 DeviceManager::DeviceManager(QObject *parent) :
     QObject(parent), deviceObject(NULL), udevListener(NULL)
 {
     movesCount = MovesCount::instance();
+    currentPersonalSettings = libambit_personal_settings_alloc();
 }
 
 DeviceManager::~DeviceManager()
@@ -35,6 +38,11 @@ DeviceManager::~DeviceManager()
     mutex.lock();
     delete udevListener;
     chargeTimer.stop();
+
+    if(currentPersonalSettings != NULL) {
+        libambit_personal_settings_free(currentPersonalSettings);
+    }
+
     mutex.unlock();
 }
 
@@ -70,6 +78,7 @@ void DeviceManager::detect()
         this->deviceObject = libambit_new(devinfo);
     }
     libambit_free_enumeration(devinfo);
+
     mutex.unlock();
 
     if (res == 0) {
@@ -77,13 +86,22 @@ void DeviceManager::detect()
     }
 }
 
-void DeviceManager::startSync(bool readAllLogs = false, bool syncTime = true, bool syncOrbit = true, bool syncMovescount = false)
+void DeviceManager::startSync(bool readAllLogs = false)
 {
+    Settings settings;
     int res = -1;
+    int waypoint_sync_res = -1;
     time_t current_time;
     struct tm *local_time;
-    uint8_t *orbitData;
+    uint8_t *orbitData = NULL;
     int orbitDataLen;
+    ambit_personal_settings_t *movecountPersonalSettings = libambit_personal_settings_alloc();
+
+    bool syncTime = settings.value("syncSettings/syncTime", true).toBool();
+    bool syncOrbit = settings.value("syncSettings/syncOrbit", true).toBool();
+    bool syncSportMode = settings.value("syncSettings/syncSportMode", false).toBool();
+    bool syncNavigation = settings.value("syncSettings/syncNavigation", false).toBool();
+    bool syncMovescount = settings.value("movescountSettings/movescountEnable", false).toBool();
 
     mutex.lock();
     this->syncMovescount = syncMovescount;
@@ -91,10 +109,15 @@ void DeviceManager::startSync(bool readAllLogs = false, bool syncTime = true, bo
     syncParts = 2;
     if (syncTime) syncParts++;
     if (syncOrbit) syncParts+=2;
+    if (syncSportMode) syncParts++;
+    if (syncMovescount) syncParts++;
 
     if (this->deviceObject != NULL) {
         emit this->syncProgressInform(QString(tr("Reading personal settings")), false, true, 0);
-        res = libambit_personal_settings_get(this->deviceObject, &currentPersonalSettings);
+
+        // Reading personal settings + waypoints
+        res = libambit_personal_settings_get(this->deviceObject, currentPersonalSettings);
+        waypoint_sync_res = libambit_navigation_read(this->deviceObject, currentPersonalSettings);
         currentSyncPart++;
 
         libambit_sync_display_show(this->deviceObject);
@@ -113,6 +136,39 @@ void DeviceManager::startSync(bool readAllLogs = false, bool syncTime = true, bo
             currentSyncPart++;
         }
 
+        if (waypoint_sync_res != -1 && syncNavigation) {
+            emit this->syncProgressInform(QString(tr("Synchronizing navigation")), false, true, 100*currentSyncPart/syncParts);
+            currentSyncPart++;
+
+            if((movesCount->getPersonalSettings(movecountPersonalSettings, true)) != -1) {
+                 movesCount->applyPersonalSettingsFromDevice(movecountPersonalSettings, currentPersonalSettings);
+                 movesCount->writePersonalSettings(movecountPersonalSettings);
+                 emit this->syncProgressInform(QString(tr("Write navigation")), false, false, 100*currentSyncPart/syncParts);
+                 libambit_navigation_write(this->deviceObject, movecountPersonalSettings);
+                 emit this->syncProgressInform(QString(tr("Synchronized navigation")), false, false, 100*currentSyncPart/syncParts);
+            }
+        }
+
+        if (syncSportMode && res != -1) {
+            emit this->syncProgressInform(QString(tr("Fetching sport modes")), false, true, 100*currentSyncPart/syncParts);
+
+            ambit_app_rules_t* ambitApps = liblibambit_malloc_app_rules();
+            movesCount->getAppsData(ambitApps);
+
+            ambit_sport_mode_device_settings_t *ambitDeviceSettings = libambit_malloc_sport_mode_device_settings();
+            if (movesCount->getCustomModeData(ambitDeviceSettings) != -1) {
+                emit this->syncProgressInform(QString(tr("Write sport modes")), false, false, 100*currentSyncPart/syncParts);
+                res = libambit_sport_mode_write(this->deviceObject, ambitDeviceSettings);
+
+                emit this->syncProgressInform(QString(tr("Write apps")), false, true, 100*currentSyncPart/syncParts);
+                res = libambit_app_data_write(this->deviceObject, ambitDeviceSettings, ambitApps);
+            }
+            libambit_sport_mode_device_settings_free(ambitDeviceSettings);
+            libambit_app_rules_free(ambitApps);
+
+            currentSyncPart++;
+        }
+
         if (syncOrbit && res != -1) {
             emit this->syncProgressInform(QString(tr("Fetching orbital data")), false, true, 100*currentSyncPart/syncParts);
             if ((orbitDataLen = movesCount->getOrbitalData(&orbitData)) != -1) {
@@ -134,6 +190,9 @@ void DeviceManager::startSync(bool readAllLogs = false, bool syncTime = true, bo
     }
     mutex.unlock();
 
+    libambit_personal_settings_free(movecountPersonalSettings);
+    movecountPersonalSettings = NULL;
+
     emit syncFinished(res >= 0);
 
     if (res == -1) {
@@ -182,7 +241,7 @@ int DeviceManager::log_skip_cb(void *ref, ambit_log_header_t *log_header)
 void DeviceManager::log_push_cb(void *ref, ambit_log_entry_t *log_entry)
 {
     DeviceManager *manager = static_cast<DeviceManager*> (ref);
-    LogEntry *entry = manager->logStore.store(manager->currentDeviceInfo, &manager->currentPersonalSettings, log_entry);
+    LogEntry *entry = manager->logStore.store(manager->currentDeviceInfo, manager->currentPersonalSettings, log_entry);
     if (entry != NULL) {
         //! TODO: make this optional, only used for debugging
         manager->movesCountXML.writeLog(entry);
diff --git a/src/openambit/devicemanager.h b/src/openambit/devicemanager.h
index d7bc1c6..feda8fd 100644
--- a/src/openambit/devicemanager.h
+++ b/src/openambit/devicemanager.h
@@ -53,7 +53,7 @@ signals:
     void syncProgressInform(QString message, bool error, bool newRow, quint8 percentDone);
 public slots:
     void detect(void);
-    void startSync(bool readAllLogs, bool syncTime, bool syncOrbit, bool syncMovescount);
+    void startSync(bool readAllLogs);
 
 private slots:
     void chargeTimerHit();
@@ -68,7 +68,7 @@ private:
     UdevListener *udevListener;
 
     DeviceInfo currentDeviceInfo;
-    ambit_personal_settings_t currentPersonalSettings;
+    ambit_personal_settings_t *currentPersonalSettings;
 
     int syncParts;
     int currentSyncPart;
diff --git a/src/openambit/main.cpp b/src/openambit/main.cpp
index cf8ce6c..9fc187b 100644
--- a/src/openambit/main.cpp
+++ b/src/openambit/main.cpp
@@ -32,6 +32,17 @@ static void initTranslations(void);
 
 int main(int argc, char *argv[])
 {
+    // Set application settings
+    QCoreApplication::setApplicationVersion(APP_VERSION);
+    QCoreApplication::setOrganizationName("Openambit");
+    QCoreApplication::setApplicationName("Openambit");
+
+    for(int x = 1; x < argc; ++x) {
+        if (QString(argv[x]) == "--version") {
+            printf("%s - Version %s\n", "Openambit", APP_VERSION);
+            return 0;
+        }
+    }
     // Handle foreground arguments
     // NOTE: It would be preferable to handle all arguments at the same place,
     // but fork needs to be done before Qt initialize it seems
@@ -63,11 +74,6 @@ int main(int argc, char *argv[])
         return 0;
     }
 
-    // Set application settings
-    QCoreApplication::setApplicationVersion(APP_VERSION);
-    QCoreApplication::setOrganizationName("Openambit");
-    QCoreApplication::setApplicationName("Openambit");
-
     // Handle forced localisation / translation
     Q_FOREACH(QString argu, a.arguments()) {
         const static QString localeParam = "-locale:";
diff --git a/src/openambit/mainwindow.cpp b/src/openambit/mainwindow.cpp
index ed8e985..bf1305c 100644
--- a/src/openambit/mainwindow.cpp
+++ b/src/openambit/mainwindow.cpp
@@ -23,8 +23,10 @@
 #include "ui_mainwindow.h"
 
 #include <QCloseEvent>
+#include <QDebug>
 #include <QListWidgetItem>
 #include <QMessageBox>
+#include <QDesktopServices>
 
 #define APPKEY                 "HpF9f1qV5qrDJ1hY1QK1diThyPsX10Mh4JvCw9xVQSglJNLdcwr3540zFyLzIC3e"
 #define MOVESCOUNT_DEFAULT_URL "https://uiservices.movescount.com/"
@@ -99,7 +101,7 @@ MainWindow::MainWindow(QWidget *parent) :
     connect(deviceManager, SIGNAL(syncProgressInform(QString,bool,bool,quint8)), this, SLOT(syncProgressInform(QString,bool,bool,quint8)), Qt::QueuedConnection);
     connect(ui->buttonDeviceReload, SIGNAL(clicked()), deviceManager, SLOT(detect()));
     connect(ui->buttonSyncNow, SIGNAL(clicked()), this, SLOT(syncNowClicked()));
-    connect(this, SIGNAL(syncNow(bool,bool,bool,bool)), deviceManager, SLOT(startSync(bool,bool,bool,bool)));
+    connect(this, SIGNAL(syncNow(bool)), deviceManager, SLOT(startSync(bool)));
     deviceWorkerThread.start();
     deviceManager->start();
     deviceManager->detect();
@@ -217,6 +219,10 @@ void MainWindow::showSettings()
     connect(settingsDialog, SIGNAL(settingsSaved()), this, SLOT(settingsSaved()));
     settingsDialog->show();
 }
+void MainWindow::showReportBug()
+{
+    QDesktopServices::openUrl(QUrl("https://github.com/openambitproject/openambit/issues"));
+}
 
 void MainWindow::showAbout()
 {
@@ -447,8 +453,6 @@ void MainWindow::updateLogList()
 
 void MainWindow::startSync()
 {
-    bool syncTime, syncOrbit, syncMovescount;
-
     ui->checkBoxResyncAll->setEnabled(false);
     ui->buttonSyncNow->setEnabled(false);
     trayIconSyncAction->setEnabled(false);
@@ -461,34 +465,29 @@ void MainWindow::startSync()
     ui->syncProgressBar->setHidden(false);
     ui->syncProgressBar->setValue(0);
 
-    settings.beginGroup("syncSettings");
-    syncTime = settings.value("syncTime", true).toBool();
-    syncOrbit = settings.value("syncOrbit", true).toBool();
-    settings.endGroup();
-    settings.beginGroup("movescountSettings");
-    syncMovescount = settings.value("movescountEnable", false).toBool();
-    settings.endGroup();
-
     trayIcon->setIcon(QIcon(":/icon_syncing"));
     if (isHidden()) {
         trayIcon->showMessage(QCoreApplication::applicationName(), tr("Syncronisation started"));
     }
-
-    emit MainWindow::syncNow(ui->checkBoxResyncAll->isChecked(), syncTime, syncOrbit, syncMovescount);
+    emit MainWindow::syncNow(ui->checkBoxResyncAll->isChecked());
 }
 
 void MainWindow::movesCountSetup()
 {
     bool syncOrbit = false;
+    bool syncSportMode = false;
+    bool syncNavigation = false;
     bool movescountEnable = false;
 
     settings.beginGroup("syncSettings");
     syncOrbit = settings.value("syncOrbit", true).toBool();
+    syncSportMode = settings.value("syncSportMode", false).toBool();
+    syncNavigation = settings.value("syncNavigation", false).toBool();
     settings.endGroup();
 
     settings.beginGroup("movescountSettings");
     movescountEnable = settings.value("movescountEnable", false).toBool();
-    if (syncOrbit || movescountEnable) {
+    if (syncOrbit || syncSportMode || syncNavigation || movescountEnable) {
         if (movesCount == NULL) {
             movesCount = MovesCount::instance();
             movesCount->setAppkey(APPKEY);
@@ -539,16 +538,34 @@ void MainWindow::LogMessageRow::setMessage(QString message)
 void MainWindow::LogMessageRow::setStatus(Status status)
 {
     QIcon icon;
+    QString str_icon = "";
 
     if (status == StatusRunning) {
-        icon = QIcon::fromTheme("task-ongoing");
+        if(QIcon::hasThemeIcon("test-ongoing")) {
+            icon = QIcon::fromTheme("task-ongoing");
+        } else {
+            str_icon = QChar(0x1a,0x23);
+        }
     }
     else if (status == StatusSuccess) {
-        icon = QIcon::fromTheme("task-complete");
+        if(QIcon::hasThemeIcon("task-complete")) {
+            icon = QIcon::fromTheme("task-complete");
+        } else {
+            str_icon = QChar(0x13,0x27);
+        }
     }
     else if (status == StatusFailed) {
-        icon = QIcon::fromTheme("task-reject");
+        if(QIcon::hasThemeIcon("task-reject")) {
+            icon = QIcon::fromTheme("task-reject");
+        } else {
+            str_icon = QChar(0x17,0x27);
+        }
+    }
+
+    if(str_icon != "") {
+        iconLabel->setText(str_icon);
+    } else {
+        iconLabel->setPixmap(icon.pixmap(8,8));
     }
-    iconLabel->setPixmap(icon.pixmap(8,8));
 }
 
diff --git a/src/openambit/mainwindow.h b/src/openambit/mainwindow.h
index 360845f..0ac9aa4 100644
--- a/src/openambit/mainwindow.h
+++ b/src/openambit/mainwindow.h
@@ -47,7 +47,7 @@ public:
     ~MainWindow();
 
 signals:
-    void syncNow(bool readAll, bool syncTime, bool syncOrbit, bool syncMovescount);
+    void syncNow(bool readAll);
 
 public slots:
     void singleApplicationMsgRecv(QString msg);
@@ -64,6 +64,7 @@ private slots:
     void trayIconClicked(QSystemTrayIcon::ActivationReason reason);
 
     void showSettings();
+    void showReportBug();
     void showAbout();
     void settingsSaved();
 
diff --git a/src/openambit/mainwindow.ui b/src/openambit/mainwindow.ui
index a4a7016..ea35572 100644
--- a/src/openambit/mainwindow.ui
+++ b/src/openambit/mainwindow.ui
@@ -346,12 +346,29 @@
     <property name="title">
      <string>&Help</string>
     </property>
+    <addaction name="actionReport_bug"/>
     <addaction name="actionAbout_openambit"/>
    </widget>
    <addaction name="menuOpenambit"/>
    <addaction name="menu_Help"/>
   </widget>
   <widget class="QStatusBar" name="statusBar"/>
+  <action name="actionReport_bug">
+   <property name="icon">
+    <iconset theme="help-faq">
+     <normaloff/>
+    </iconset>
+   </property>
+   <property name="text">
+    <string>Report bug...</string>
+   </property>
+   <property name="iconText">
+    <string>Report bug...</string>
+   </property>
+   <property name="toolTip">
+    <string>Report bug...</string>
+   </property>
+  </action>
   <action name="actionAbout_openambit">
    <property name="icon">
     <iconset theme="help-about">
@@ -427,6 +444,22 @@
    </hints>
   </connection>
   <connection>
+   <sender>actionReport_bug</sender>
+   <signal>triggered()</signal>
+   <receiver>MainWindow</receiver>
+   <slot>showReportBug()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>-1</x>
+     <y>-1</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>435</x>
+     <y>270</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
    <sender>actionAbout_openambit</sender>
    <signal>triggered()</signal>
    <receiver>MainWindow</receiver>
diff --git a/src/openambit/settingsdialog.cpp b/src/openambit/settingsdialog.cpp
index 222753f..2da4a8f 100644
--- a/src/openambit/settingsdialog.cpp
+++ b/src/openambit/settingsdialog.cpp
@@ -76,6 +76,8 @@ void SettingsDialog::readSettings()
     ui->checkBoxSyncAutomatically->setChecked(settings.value("syncAutomatically", false).toBool());
     ui->checkBoxSyncTime->setChecked(settings.value("syncTime", true).toBool());
     ui->checkBoxSyncOrbit->setChecked(settings.value("syncOrbit", true).toBool());
+    ui->checkBoxSyncSportsMode->setChecked(settings.value("syncSportMode", false).toBool());
+    ui->checkBoxSyncNavigation->setChecked(settings.value("syncNavigation", false).toBool());
     settings.endGroup();
 
     settings.beginGroup("movescountSettings");
@@ -97,6 +99,8 @@ void SettingsDialog::writeSettings()
     settings.setValue("syncAutomatically", ui->checkBoxSyncAutomatically->isChecked());
     settings.setValue("syncTime", ui->checkBoxSyncTime->isChecked());
     settings.setValue("syncOrbit", ui->checkBoxSyncOrbit->isChecked());
+    settings.setValue("syncSportMode", ui->checkBoxSyncSportsMode->isChecked());
+    settings.setValue("syncNavigation", ui->checkBoxSyncNavigation->isChecked());
     settings.endGroup();
 
     settings.beginGroup("movescountSettings");
diff --git a/src/openambit/settingsdialog.ui b/src/openambit/settingsdialog.ui
index 7dca610..d560839 100644
--- a/src/openambit/settingsdialog.ui
+++ b/src/openambit/settingsdialog.ui
@@ -6,7 +6,7 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>729</width>
+    <width>734</width>
     <height>438</height>
    </rect>
   </property>
@@ -144,7 +144,7 @@
                 </property>
                </widget>
               </item>
-              <item row="2" column="0">
+              <item row="3" column="0">
                <widget class="QCheckBox" name="checkBoxSyncOrbit">
                 <property name="text">
                  <string>Sync orbital data (from Movescount)</string>
@@ -158,6 +158,20 @@
                 </property>
                </widget>
               </item>
+              <item row="4" column="0">
+               <widget class="QCheckBox" name="checkBoxSyncSportsMode">
+                <property name="text">
+                 <string>Sync sport modes (from Movescount)</string>
+                </property>
+               </widget>
+              </item>
+              <item row="5" column="0">
+               <widget class="QCheckBox" name="checkBoxSyncNavigation">
+                <property name="text">
+                 <string>Sync navigation (from Movescount)</string>
+                </property>
+               </widget>
+              </item>
              </layout>
             </widget>
            </item>
diff --git a/src/openambit/translations/openambit_de.ts b/src/openambit/translations/openambit_de.ts
index 913b89c..c604e21 100644
--- a/src/openambit/translations/openambit_de.ts
+++ b/src/openambit/translations/openambit_de.ts
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE TS>
-<TS version="2.0" language="de_DE" sourcelanguage="en">
+<TS version="2.1" language="de_DE" sourcelanguage="en">
 <context>
     <name>ConfirmBetaDialog</name>
     <message>
@@ -82,6 +82,30 @@ p, li { white-space: pre-wrap; }
         <source>Downloading log %1 of %2</source>
         <translation>Lade Log %1 von %2 herunter</translation>
     </message>
+    <message>
+        <source>Synchronizing navigation</source>
+        <translation>Synchronisiere Navigation</translation>
+    </message>
+    <message>
+        <source>Write navigation</source>
+        <translation>Schreibe Navigation</translation>
+    </message>
+    <message>
+        <source>Synchronized navigation</source>
+        <translation>Navigation synchronisiert</translation>
+    </message>
+    <message>
+        <source>Fetching sport modes</source>
+        <translation>Hole Sportmodi</translation>
+    </message>
+    <message>
+        <source>Write sport modes</source>
+        <translation>Schreibe Sportmodi</translation>
+    </message>
+    <message>
+        <source>Write apps</source>
+        <translation>Schreibe Apps</translation>
+    </message>
 </context>
 <context>
     <name>LogView</name>
@@ -252,6 +276,10 @@ p, li { white-space: pre-wrap; }
         <source>Downloading %1%</source>
         <translation>Synchronisieren %1%</translation>
     </message>
+    <message>
+        <source>Report bug...</source>
+        <translation>Fehler melden...</translation>
+    </message>
 </context>
 <context>
     <name>QObject</name>
@@ -332,5 +360,13 @@ Zeile %2, Spalte %3</translation>
         <source>Email (Movescount account)</source>
         <translation>Email des Movescount-Accounts</translation>
     </message>
+    <message>
+        <source>Sync sport modes (from Movescount)</source>
+        <translation>Sportmodi (von Movescount) synchronisieren</translation>
+    </message>
+    <message>
+        <source>Sync navigation (from Movescount)</source>
+        <translation>Navigation (von Movescount) synchronisieren</translation>
+    </message>
 </context>
 </TS>
diff --git a/src/openambit/translations/openambit_de.ts b/src/openambit/translations/openambit_nb_NO.ts
similarity index 73%
copy from src/openambit/translations/openambit_de.ts
copy to src/openambit/translations/openambit_nb_NO.ts
index 913b89c..a028049 100644
--- a/src/openambit/translations/openambit_de.ts
+++ b/src/openambit/translations/openambit_nb_NO.ts
@@ -1,15 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE TS>
-<TS version="2.0" language="de_DE" sourcelanguage="en">
+<TS version="2.0" language="nb_NO">
 <context>
     <name>ConfirmBetaDialog</name>
     <message>
         <source>Openambit: Disclaimer</source>
-        <translation>Openambit: Disclaimer</translation>
+        <translation>Openambit: Advarsel</translation>
     </message>
     <message>
         <source>Don't ask me again, I really want to use Openambit</source>
-        <translation>Nicht nochmal fragen, ich möchte Openambit wirklich benutzen</translation>
+        <translation>Ikke spør meg igjen. Jeg vil bruke Openambit.</translation>
     </message>
     <message>
         <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
@@ -31,95 +31,108 @@ p, li { white-space: pre-wrap; }
 <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Thanks </p>
 <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Courier New,courier'; color:#008000;"><br /></p>
 <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Courier New,courier'; color:#008000;"><br /></p></body></html></source>
-        <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">FRÜHE BETA-SOFTWARE: <a href="http://de.wikipedia.org/wiki/Hic_sunt_dracones"><span style=" text-decoration: underline; color:#0000ff;">hic sunt dracones</span></a></p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Diese Software ist noch in einem frühen Beta-Stadium. Sie lädt möglicherweise ungültige Log-Dateien zu Movescount hoch, die nicht überschrieben werden können oder andere unerwartete Effekte hervorrufen.</p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#008000;">Openambit ist freie Software: Du kannst sie weitergeben und verändern </span><span style=" font-family:'Courier New,courier'; color:#008000;">entsprechend den Bedingungen der GNU General Public License, veröffentlicht von der Free Software Foundation, in Version 3 oder (nach dei [...]
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Courier New,courier';"><br /></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier New,courier'; color:#008000;">Dieses Programm wird in der Hoffnung weitergegeben, nützlich zu sein, aber OHNE JEGLICHE GEWÄHRLEISTUNG, insbesondere OHNE MÄNGELHAFTUNG oder die ZUSICHERUNG, dass es FÜR EINEN BESTIMMTEN ZWECK GEEIGNET ist. Für weitere Details wird auf die GNU General Public Licens [...]
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Bitte benutze dieses Programm auf <span style=" text-decoration: underline;">eigene Gefahr</span> und nur, wenn du die damit verbundenen Risiken verstanden hast.</p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Wenn du dich entschlossen hast, Openambit zu benutzen, dann <a href="https://github.com/openambitproject/openambit/issues/new"><span style=" text-decoration: underline; color:#0000ff;">melde bitte Fehler</span></a>, damit wir das Programm weiter verbessern können.</p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Danke </p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Courier New,courier'; color:#008000;"><br /></p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Courier New,courier'; color:#008000;"><br /></p></body></html></translation>
+        <translation type="unfinished"></translation>
     </message>
 </context>
 <context>
     <name>DeviceManager</name>
     <message>
         <source>Reading personal settings</source>
-        <translation>Lese persönliche Einstellungen</translation>
+        <translation>Leser personlige innstillinger</translation>
     </message>
     <message>
         <source>Setting date/time</source>
-        <translation>Setze Datum und Zeit</translation>
+        <translation>Oppdaterer dato/tid</translation>
     </message>
     <message>
         <source>Reading log files</source>
-        <translation>Lese Log-Dateien</translation>
+        <translation>Leser loggfiler</translation>
     </message>
     <message>
         <source>Fetching orbital data</source>
-        <translation>Hole GPS-Bahndaten</translation>
+        <translation>Henter GPS-data</translation>
     </message>
     <message>
         <source>Writing orbital data</source>
-        <translation>Schreibe GPS-Bahndaten</translation>
+        <translation>Oppdaterer GPS-data</translation>
     </message>
     <message>
         <source>Failed to get orbital data</source>
-        <translation>Fehler beim Holen der GPS-Bahndaten</translation>
+        <translation>Kunne ikke hente GPS-data</translation>
     </message>
     <message>
         <source>Downloading log %1 of %2</source>
-        <translation>Lade Log %1 von %2 herunter</translation>
+        <translation>Henter logg %1 av %2</translation>
+    </message>
+    <message>
+        <source>Synchronizing navigation</source>
+        <translation>Synkoroniserer navigasjon</translation>
+    </message>
+    <message>
+        <source>Write navigation</source>
+        <translation>Skriver navigasjon</translation>
+    </message>
+    <message>
+        <source>Synchronized navigation</source>
+        <translation>Navigasjon synkronisert</translation>
+    </message>
+    <message>
+        <source>Fetching sport modes</source>
+        <translation>Henter sportmoduser</translation>
+    </message>
+    <message>
+        <source>Write sport modes</source>
+        <translation>Skriver sportmoduser</translation>
+    </message>
+    <message>
+        <source>Write apps</source>
+        <translation>Skriver apps</translation>
+    </message>
+</context>
+<context>
+    <name>LogEntry</name>
+    <message>
+        <source>Device</source>
+        <translation type="obsolete">Enhet</translation>
     </message>
 </context>
 <context>
     <name>LogView</name>
     <message>
         <source>see on movescount.com</source>
-        <translation>auf Movescount.com ansehen</translation>
+        <translation>se på movescount.com</translation>
     </message>
     <message>
         <source>Not uploaded yet</source>
-        <translation>Noch nicht hochgeladen</translation>
+        <translation>Ikke lastet opp</translation>
     </message>
     <message>
         <source>Details</source>
-        <translation>Details</translation>
+        <translation>Detaljer</translation>
     </message>
     <message>
         <source>Duration: %1</source>
-        <translation>Dauer: %1</translation>
+        <translation>Tid: %1</translation>
     </message>
     <message>
         <source>Distance: %1 m</source>
-        <translation>Distanz: %1 m</translation>
+        <translation>Distanse: %1 m</translation>
     </message>
     <message>
         <source>Training values</source>
-        <translation>Trainingswerte</translation>
+        <translation>Treningsverider</translation>
     </message>
     <message>
         <source>Avg HR: %1 bpm</source>
-        <translation>Durchschnittspuls: %1 bpm</translation>
+        <translation>Snittpuls: %1 slag/min</translation>
     </message>
     <message>
         <source>Max HR: %1 bpm</source>
-        <translation>Maximalpuls: %1 bpm</translation>
+        <translation>Makspuls: %1 slag/min</translation>
     </message>
     <message>
         <source>Min HR: %1 bpm</source>
-        <translation>Minimalpuls: %1 bpm</translation>
+        <translation>Minpuls: %1 slag/min</translation>
     </message>
     <message>
         <source>PTE: %1</source>
@@ -127,143 +140,147 @@ p, li { white-space: pre-wrap; }
     </message>
     <message>
         <source>Device</source>
-        <translation>Gerät</translation>
+        <translation>Enhet</translation>
     </message>
     <message>
         <source>Name: %1</source>
-        <translation>Name: %1</translation>
+        <translation>Modell: %1</translation>
     </message>
     <message>
         <source>Variant: %1</source>
-        <translation>Variante: %1</translation>
+        <translation>Variant: %1</translation>
     </message>
     <message>
         <source>Serial: %1</source>
-        <translation>Seriennummer: %1</translation>
+        <translation>Serienummer: %1</translation>
     </message>
 </context>
 <context>
     <name>MainWindow</name>
     <message>
-        <source>Openambit</source>
-        <translation>Openambit</translation>
+        <source>Sync now</source>
+        <translation>Synkroniser</translation>
     </message>
     <message>
-        <source>Device</source>
-        <translation>Gerät</translation>
+        <source>Minimize</source>
+        <translation>Minimer</translation>
     </message>
     <message>
-        <source>No device detected</source>
-        <translation>Kein Gerät gefunden</translation>
+        <source>Restore</source>
+        <translation>Gjenopprett</translation>
     </message>
     <message>
-        <source>Device not supported yet!</source>
-        <translation>Gerät noch nicht unterstützt!</translation>
+        <source>About %1</source>
+        <translation>Om %1</translation>
     </message>
     <message>
-        <source>Auth on <a href="http://www.movescount.com"><span style=" text-decoration: underline; color:#0057ae;">movescount.com</span></a>!</source>
-        <translation>Authorisieren bei <a href="http://www.movescount.com"><span style=" text-decoration: underline; color:#0057ae;">movescount.com</span></a>!</translation>
+        <source><h2>%1</h2><b>Version %2</b><br />Using Qt %3</source>
+        <translation><h2>%1</h2><b>Version %2</b><br />Qt %3</translation>
     </message>
     <message>
-        <source>Charge:</source>
-        <translation>Ladestand:</translation>
+        <source>No device detected</source>
+        <translation>Finner ingen enhet</translation>
     </message>
     <message>
-        <source>Resync all</source>
-        <translation>Alle erneut synchronisieren</translation>
+        <source>Syncronization complete</source>
+        <translation>Synkronisering fullført</translation>
     </message>
     <message>
-        <source>Sync now</source>
-        <translation>Jetzt synchronisieren</translation>
+        <source>Syncronisation finished</source>
+        <translation>Synkroniseringen er fullført</translation>
     </message>
     <message>
-        <source>&File</source>
-        <translation>&Datei</translation>
+        <source>Syncronization failed</source>
+        <translation>Synkroniseringen feilet</translation>
     </message>
     <message>
-        <source>&Help</source>
-        <translation>&Hilfe</translation>
+        <source>Syncronisation failed</source>
+        <translation>Synkroniseringen feilet</translation>
     </message>
     <message>
-        <source>About Openambit...</source>
-        <translation>Über Openambit...</translation>
+        <source>Newer firmware exists (%1.%2.%3)</source>
+        <translation>Det finnes en nyere firmware (%1.%2.%3)</translation>
     </message>
     <message>
-        <source>E&xit</source>
-        <translation>B&enden</translation>
+        <source>Context menu</source>
+        <translation>Meny</translation>
     </message>
     <message>
-        <source>&Settings</source>
-        <translation>&Einstellungen</translation>
+        <source>Write Movescount file</source>
+        <translation>Skriv Movescount-fil</translation>
     </message>
     <message>
-        <source>Minimize</source>
-        <translation>Minimieren</translation>
+        <source>Syncronisation started</source>
+        <translation>Synkronisering startet</translation>
     </message>
     <message>
-        <source>Restore</source>
-        <translation>Wiederherstellen</translation>
+        <source>Openambit</source>
+        <translation>Openambit</translation>
     </message>
     <message>
-        <source>About %1</source>
-        <translation>Über %1</translation>
+        <source>Device</source>
+        <translation>Enhet</translation>
     </message>
     <message>
-        <source><h2>%1</h2><b>Version %2</b><br />Using Qt %3</source>
-        <translation><h2>%1</h2><b>Version %2</b><br />Unter Verwendung von Qt %3</translation>
+        <source>Device not supported yet!</source>
+        <translation>Enheten støttes ikke ennå!</translation>
     </message>
     <message>
-        <source>Syncronization complete</source>
-        <translation>Synchronisierung abgeschlossen</translation>
+        <source>Auth on <a href="http://www.movescount.com"><span style=" text-decoration: underline; color:#0057ae;">movescount.com</span></a>!</source>
+        <translation>Tillat Openambit på <a href="http://www.movescount.com"><span style=" text-decoration: underline; color:#0057ae;">movescount.com</span></a>!</translation>
     </message>
     <message>
-        <source>Syncronisation finished</source>
-        <translation>Synchronisierung beendet</translation>
+        <source>Charge:</source>
+        <translation>Lader:</translation>
     </message>
     <message>
-        <source>Syncronization failed</source>
-        <translation>Synchronisierung fehlgeschlagen</translation>
+        <source>Resync all</source>
+        <translation>Synkroniser alt på nytt</translation>
     </message>
     <message>
-        <source>Syncronisation failed</source>
-        <translation>Synchronisierung fehlgeschlagen</translation>
+        <source>&File</source>
+        <translation>&Fil</translation>
     </message>
     <message>
-        <source>Newer firmware exists (%1.%2.%3)</source>
-        <translation>Neuere Firmware verfügbar (%1.%2.%3)</translation>
+        <source>&Help</source>
+        <translation>&Hjelp</translation>
     </message>
     <message>
-        <source>Context menu</source>
-        <translation>Kontextmenü</translation>
+        <source>About Openambit...</source>
+        <translation>Om Openambit...</translation>
     </message>
     <message>
-        <source>Write Movescount file</source>
-        <translation>Schreibe Movescount-Datei</translation>
+        <source>E&xit</source>
+        <translation>A&vslutt</translation>
     </message>
     <message>
-        <source>Syncronisation started</source>
-        <translation>Synchronisierung gestartet</translation>
+        <source>&Settings</source>
+        <translation>&Innstillinger</translation>
     </message>
     <message>
         <source>Charging %1%</source>
-        <translation>Laden %1%</translation>
+        <translation>Lader %1%</translation>
     </message>
     <message>
         <source>Downloading %1%</source>
-        <translation>Synchronisieren %1%</translation>
+        <translation>Laster ned %1%</translation>
+    </message>
+    <message>
+        <source>Report bug...</source>
+        <translation>Rapporter feil...</translation>
     </message>
 </context>
 <context>
     <name>QObject</name>
     <message>
         <source>The file is not an openambit version 1.0 file.</source>
-        <translation>Die Datei hat nicht die Openambit-Version 1.0.</translation>
+        <translation>Filen er ikke i openambit version 1.0-format.</translation>
     </message>
     <message>
         <source>%1
 Line %2, column %3</source>
         <translation>%1
-Zeile %2, Spalte %3</translation>
+Rad %2, kolonne %3</translation>
     </message>
 </context>
 <context>
@@ -274,11 +291,11 @@ Zeile %2, Spalte %3</translation>
     </message>
     <message>
         <source>General</source>
-        <translation>Allgemein</translation>
+        <translation>Generelt</translation>
     </message>
     <message>
         <source>Device sync</source>
-        <translation>Gerätesynchronisierung</translation>
+        <translation>Synkronisering</translation>
     </message>
     <message>
         <source>Movescount</source>
@@ -286,51 +303,59 @@ Zeile %2, Spalte %3</translation>
     </message>
     <message>
         <source>General settings</source>
-        <translation>Allgemeine Einstellungen</translation>
+        <translation>Generelle innstillinger</translation>
     </message>
     <message>
         <source>Skip Beta check at startup</source>
-        <translation>Beta-Warnung beim Start nicht anzeigen </translation>
+        <translation>Vis ikke beta-advarsel i oppstarten</translation>
     </message>
     <message>
         <source>Continue running in background when Openambit main window is closed</source>
-        <translation>Im Hintergrund weiter ausführen wenn das Hauptfenster geschlossen wird</translation>
+        <translation>La Openambit kjøre i bakgrunnen selv om du lukker vinduet</translation>
     </message>
     <message>
         <source>Device syncronisation settings</source>
-        <translation>Einstellungen für die Gerätesynchronisierung</translation>
+        <translation>Synkroniseringsinnstillinger</translation>
     </message>
     <message>
         <source>Sync time from computer</source>
-        <translation>Zeit vom Computer synchronisieren</translation>
+        <translation>Synkroniser enhet med tid fra PC</translation>
     </message>
     <message>
         <source>Sync orbital data (from Movescount)</source>
-        <translation>GPS-Satellitenbahndaten (von Movescount) synchronisieren</translation>
+        <translation>Synkroniser GPS-data (fra Movescount)</translation>
     </message>
     <message>
         <source>Start sync automatically when device connected</source>
-        <translation>Synchronisierung automatisch starten, wenn ein Gerät angeschlossen ist</translation>
+        <translation>Start synkronisering automatiskt når enheten tilkobles</translation>
     </message>
     <message>
         <source>Movescount connectivity</source>
-        <translation>Verbindung zu Movescount</translation>
+        <translation>Movescount-innstillinger</translation>
     </message>
     <message>
         <source>Check Movescount for new versions</source>
-        <translation>Auf Movescount nach neuen Versionen suchen</translation>
+        <translation>Let etter firmware-oppdatering hos Movescount</translation>
     </message>
     <message>
         <source>Generate debug files (XMLs stored in ~/.openambit/movescount)</source>
-        <translation>Debug-Dateien erzeugen (XML-Dateien in ~/.openambit/movescount)</translation>
+        <translation>Generer feilsøkningsfiler (XML-filer som lagres i ~/.openambit/movescount)</translation>
     </message>
     <message>
         <source>Sync logs with Movescount</source>
-        <translation>Logs zu Movescount synchronisieren</translation>
+        <translation>Last opp logger til Movescount</translation>
     </message>
     <message>
         <source>Email (Movescount account)</source>
-        <translation>Email des Movescount-Accounts</translation>
+        <translation>E-post (til din Movescount-konto)</translation>
+    </message>
+    <message>
+        <source>Sync sport modes (from Movescount)</source>
+        <translation>Synkroniser sportmoduser (fra Movescount)</translation>
+    </message>
+    <message>
+        <source>Sync navigation (from Movescount)</source>
+        <translation>Synkroniser navigasjon (fra Movescount)</translation>
     </message>
 </context>
 </TS>
diff --git a/tools/openambit2gpx.py b/tools/openambit2gpx.py
index 60e1ebe..47bc901 100644
--- a/tools/openambit2gpx.py
+++ b/tools/openambit2gpx.py
@@ -44,6 +44,7 @@ timeLast=None
 altitudeLast=None
 hrLast=None
 cadenceLast=None
+powerLast=None
 speedLast=None
 tempLast=None
 airpressureLast=None
@@ -93,6 +94,7 @@ for element in rootIn.iterfind("Log/Samples/Sample"):
     altitude=element.findtext("Altitude") if element.findtext("Altitude")!=None else altitudeLast
     hr=element.findtext("HR") if element.findtext("HR")!=None else hrLast
     cadence=element.findtext("Cadence") if element.findtext("Cadence")!=None else cadenceLast
+    power=element.findtext("BikePower") if element.findtext("BikePower")!=None else powerLast
     speed=element.findtext("Speed") if element.findtext("Speed")!=None else speedLast
     temp=str(float(element.findtext("Temperature"))/10) if element.findtext("Temperature")!=None else tempLast
     airpressure=element.findtext("SeaLevelPressure") if element.findtext("SeaLevelPressure")!=None else airpressureLast
@@ -144,11 +146,12 @@ for element in rootIn.iterfind("Log/Samples/Sample"):
         elif timeLast!=None:
             etree.SubElement(trk,"time").text=timeLast 
 
-        if hr!=None or cadence!=None or speed!=None or temp!=None or airpressure!=None:
+        if hr!=None or cadence!=None or power!=None or speed!=None or temp!=None or airpressure!=None:
             extGpx=etree.SubElement(trk,"extensions")
             if hr!=None: etree.SubElement(extGpx,"gpxdata:hr").text=hr
             if cadence!=None: etree.SubElement(extGpx,"gpxdata:cadence").text=cadence
-            if temp!=None: etree.SubElement(extGpx,"gpxdata:atemp").text=temp
+            if power!=None: etree.SubElement(extGpx,"gpxdata:power").text=power
+            if temp!=None: etree.SubElement(extGpx,"gpxdata:temp").text=temp
             if speed!=None: etree.SubElement(extGpx,"gpxdata:speed").text=speed
             if airpressure!=None: etree.SubElement(extGpx,"gpxdata:SeaLevelPressure").text=airpressure
 
@@ -160,6 +163,7 @@ for element in rootIn.iterfind("Log/Samples/Sample"):
     altitudeLast=altitude
     hrLast=hr
     cadenceLast=cadence
+    powerLast=power
     speedLast=speed
     tempLast=temp
     airpressureLast=airpressure
@@ -170,6 +174,7 @@ for element in rootIn.iterfind("Log/Samples/Sample"):
     altitude=None
     hr=None
     cadence=None
+    power=None
     speed=None
     temp=None
     airpressure=None
diff --git a/wireshark_dissector/CMakeLists.txt b/wireshark_dissector/CMakeLists.txt
index 45a932b..e93506c 100644
--- a/wireshark_dissector/CMakeLists.txt
+++ b/wireshark_dissector/CMakeLists.txt
@@ -26,7 +26,8 @@ project(ambit-wireshark-plugin C)
 cmake_minimum_required(VERSION 2.6)
 set(CMAKE_BACKWARDS_COMPATIBILITY 2.6)
 set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
-set(CMAKE_INSTALL_LIBDIR ~/.wireshark)
+set(CMAKE_INSTALL_WIRESHARKPLUGINSDIR ~/.wireshark
+    CACHE PATH "Where to install wireshark plugins")
 
 INCLUDE(UseMakeDissectorReg)
   
@@ -80,6 +81,6 @@ set_target_properties(ws-ambit PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}")
 target_link_libraries(ws-ambit ${WIRESHARK_LIBRARIES})
 
 install(TARGETS ws-ambit
-	LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/plugins NAMELINK_SKIP
+	LIBRARY DESTINATION ${CMAKE_INSTALL_WIRESHARKPLUGINSDIR} NAMELINK_SKIP
 )
 
diff --git a/wireshark_dissector/ambit-dissector.c b/wireshark_dissector/ambit-dissector.c
index fe6eb16..5d80380 100644
--- a/wireshark_dissector/ambit-dissector.c
+++ b/wireshark_dissector/ambit-dissector.c
@@ -1,5 +1,6 @@
 #include "config.h"
 
+#include "stdio.h"
 #include <glib.h>
 #include <epan/conversation.h>
 #include <epan/expert.h>
@@ -65,6 +66,20 @@ static gint dissect_ambit_gps_data_peek_get(tvbuff_t *tvb, packet_info *pinfo, p
 static gint dissect_ambit_gps_data_peek_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_);
 static gint dissect_ambit_data_write(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_);
 static gint dissect_ambit_data_write_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_);
+static gint dissect_ambit_data_write_content(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length);
+//static uint dissect_ambit_data_write_read_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength);
+static uint dissect_ambit_data_get_length_to_read(guint32 *offset, guint32 length, guint16 packageLength);
+static gint dissect_ambit_data_write_sport_modes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 address, guint32 length);
+static gint dissect_ambit_data_write_apps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 address, guint32 length);
+static uint dissect_ambit_data_write_read_data_0101(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength);
+static uint dissect_ambit_data_write_read_data_0102(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength);
+static uint dissect_ambit_data_write_read_data_0105(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength);
+static uint dissect_ambit_data_write_read_data_0106(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength);
+static uint dissect_ambit_data_write_read_data_0107(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength);
+static uint dissect_ambit_data_write_read_data_0108(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength);
+static uint dissect_ambit_data_write_read_data_0109(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength);
+static uint dissect_ambit_data_write_read_data_010a(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength);
+static uint dissect_ambit_data_write_read_data_010c(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength);
 
 static gint dissect_ambit3_settings_get(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_);
 static gint dissect_ambit3_settings_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_);
@@ -271,6 +286,38 @@ static gint ett_ambit_log_sample = -1;
 static gint ett_ambit3_log_headers = -1;
 static gint ett_ambit3_log_header = -1;
 
+static int hf_ambit_write_data_length = -1;
+static int hf_ambit_write_data_header = -1;
+static int hf_ambit_write_data_activity_id = -1;
+static gint hf_ambit_write_data_interval_repetitions = -1;
+static gint hf_ambit_write_data_show_navigation = -1;
+static gint hf_ambit_write_data_alti_baro_mode = -1;
+static gint hf_ambit_write_data_use_hrbelt_and_pods = -1;
+static gint hf_ambit_write_data_recording_interval = -1;
+static gint hf_ambit_write_data_auto_lap = -1;
+static gint hf_ambit_write_data_auto_pause = -1;
+static gint hf_ambit_write_auto_scroll = -1;
+static gint hf_ambit_write_data_use_interval_timer = -1;
+static gint hf_ambit_write_data_interval_timer_time = -1;
+static gint hf_ambit_write_data_interval_timer_max = -1;
+static gint hf_ambit_write_data_interval_timer_min = -1;
+static gint hf_ambit_write_data_use_hr_limits = -1;
+static gint hf_ambit_write_data_backlight = -1;
+static gint hf_ambit_write_data_display = -1;
+static gint hf_ambit_write_data_display_type = -1;
+static gint hf_ambit_write_quick_navigation  = -1;
+static gint hf_ambit_write_data_gps_interval = -1;
+static gint hf_ambit_log_activity_custom_mode_row = -1;
+static gint hf_ambit_log_activity_custom_mode_display = -1;
+static gint hf_ambit_log_activity_custom_mode_view = -1;
+
+static gint hf_ambit_write_data_apps_nbr_of = -1;
+static gint hf_ambit_write_data_apps_header_len = -1;
+static gint hf_ambit_write_data_apps_end_pos = -1;
+static gint hf_ambit_write_data_app_data = -1;
+static gint hf_ambit_write_data_app_checksum = -1;
+static gint hf_ambit_write_data_app_index = -1;
+
 static ambit_reassembly_entry_t *reassembly_entries = NULL;
 static guint32 reassembly_entries_alloc = 0;
 
@@ -348,6 +395,73 @@ static const value_string log_samples_swimming_style_vals[] = {
     { 0, NULL }
 };
 
+static const value_string custom_modes_alti_baro_mode_vals[] = {
+    { 0x00, "Alti" },
+    { 0x01, "Baro" },
+    { 0x02, "Automatic" },
+    { 0, NULL }
+};
+
+static const value_string custom_modes_backlight_vals[] = {
+    { 0x00, "Normal" },
+    { 0x01, "Off" },
+    { 0x02, "Night" },
+    { 0x03, "Toggle" },
+    { 0xff, "Default" },
+    { 0, NULL }
+};
+
+static const value_string custom_modes_display_vals[] = {
+    { 0x00, "Light" },
+    { 0x01, "Dark" },
+    { 0xff, "Default" },
+    { 0, NULL }
+};
+
+static const value_string custom_modes_quick_navigation_vals[] = {
+    { 0x00, "Off" },
+    { 0x01, "POI" },
+    { 0x02, "Route" },
+    { 0, NULL }
+};
+
+static const value_string custom_modes_gps_accuracy_vals[] = {
+    { 0x00, "GPS Off" },
+    { 0x01, "GPS Best (16h)" },
+    { 0x05, "GPS Good (24h)" },
+    { 0x3c, "GPS Ok (50h)" },
+    { 0, NULL }
+};
+
+static const value_string custom_modes_interval_timer_unit_vals[] = {
+    { 0x0000, "meter" },
+    { 0x0100, "sec" },
+    { 0, NULL }
+};
+
+static const value_string custom_modes_display_type_val[] = {
+    { 0x0101, "Barograph display" },
+    { 0x0104, "3 rows display" },
+    { 0x0105, "2 rows display" },
+    { 0x0106, "1 row display" },
+    { 0, NULL }
+};
+
+static const value_string custom_modes_header_vals[] = {
+    { 0x0100, "[Custom modes header]" },
+    { 0x0101, "[Custom mode activity header]" },
+    { 0x0102, "[Custom mode activity settings header]" },
+    { 0x0104, "[Unknown header] ????" },
+    { 0x0105, "[Display header]" },
+    { 0x0106, "[Display page header]" },
+    { 0x0107, "[Display ???? header]" },
+    { 0x0108, "[Display row ???? header]" },
+    { 0x0109, "[Row header]" },
+    { 0x010a, "[View header (lower row)]" },
+    { 0x010b, "[Unknown header] ????" },
+    { 0, NULL }
+};
+
 static const ambit_protocol_type_t subdissectors[] = {
     { 0x03000500, "Set time", dissect_ambit_time_write },
     { 0x03000a00, "Time reply", dissect_ambit_time_reply },
@@ -1698,12 +1812,490 @@ static gint dissect_ambit_gps_data_peek_reply(tvbuff_t *tvb, packet_info *pinfo,
 
 static gint dissect_ambit_data_write(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
 {
+    guint32 address = tvb_get_letohl(tvb, 0);
     guint32 length = tvb_get_letohl(tvb, 4);
 
     proto_tree_add_item(tree, hf_ambit_log_data_address, tvb, 0, 4, ENC_LITTLE_ENDIAN);
     proto_tree_add_item(tree, hf_ambit_log_data_length, tvb, 4, 4, ENC_LITTLE_ENDIAN);
+/*
+    if (address >= 0x2000 && address <= 0x3800) { // Custom sport modes address.
+        dissect_ambit_data_write_sport_modes(tvb, pinfo, tree, address, length + 8);
+    }
+    else if (address >= 0x927c0 && address <= 0x9a7c0) {
+        dissect_ambit_data_write_apps(tvb, pinfo, tree, address, length + 8);
+    }
+    else {
+        proto_tree_add_text(tree, tvb, 8, length, "Payload");
+    }
+*/
+    if ((address >= 0x2000 && address <= 0x3800) || (address >= 0x927c0 && address <= 0x9a7c0)) { // Custom sport modes address.
+        int i;
+        for (i=0; i<length+8; i++) {
+            g_printf("%.2x", tvb_get_guint8(tvb,i));
+        }
+        g_printf("\n");
+
+    }
+}
+
+
+static gint dissect_ambit_data_write_sport_modes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 address, guint32 length)
+{
+    guint32 offset = 8;
+
+    static guint32 leftToReadArray[6] = {0};
+    int index = (address - 0x2000) / 0x400;
+    uint leftToRead = leftToReadArray[index];
+
+    if (leftToRead)
+    {
+        dissect_ambit_add_unknown(tvb, pinfo, tree, offset, leftToRead);
+        offset += leftToRead;
+    }
+
+
+    if (address == 0x00002000)
+    {
+        proto_tree_add_item(tree, hf_ambit_write_data_header, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+        offset += 2;
+
+        proto_tree_add_item(tree, hf_ambit_write_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+        offset += 2;
+
+        proto_tree_add_item(tree, hf_ambit_write_data_header, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+        offset += 2;
+
+        proto_tree_add_item(tree, hf_ambit_write_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+        offset += 2;
 
-    proto_tree_add_text(tree, tvb, 8, length, "Payload");
+        proto_tree_add_item(tree, hf_ambit_write_data_header, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+        offset += 2;
+
+        proto_tree_add_item(tree, hf_ambit_write_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+        offset += 2;
+
+        dissect_ambit_add_unknown(tvb, pinfo, tree, offset, 2);
+        offset += 2;
+    }
+
+    leftToRead = dissect_ambit_data_write_content(tvb, pinfo, tree, &offset, length);
+    leftToReadArray[index + 1] = leftToRead;
+}
+
+static gint dissect_ambit_data_write_apps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 address, guint32 length)
+{
+    static u_int32_t apps_length[10] = {0};
+
+    static guint32 leftToReadArray[6] = {0};
+    static guint32 currentAppIndexArray[6] = {0};
+    int arrayIndex = (address - 0x927c0) / 0x400;
+    uint leftToRead = leftToReadArray[arrayIndex];
+    uint currentAppIndex = currentAppIndexArray[arrayIndex];
+    uint header_len = 0;
+
+    guint32 offset = 8;
+
+    if (address == 0x927c0) {
+        proto_tree_add_item(tree, hf_ambit_write_data_apps_nbr_of, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+        offset += 2;
+
+        dissect_ambit_add_unknown(tvb, pinfo, tree, offset, 1);
+        offset += 1;
+
+        proto_tree_add_item(tree, hf_ambit_write_data_apps_header_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+        header_len = tvb_get_letohs(tvb, offset);
+        offset += 2;
+
+        dissect_ambit_add_unknown(tvb, pinfo, tree, offset, 2);
+        offset += 2;
+
+        int i;
+        for (i=0; i*4<header_len-7; i++)
+        {
+            proto_tree_add_item(tree, hf_ambit_write_data_apps_end_pos, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+            apps_length[i] = tvb_get_letohl(tvb, offset) - header_len;
+            offset += 4;
+        }
+    }
+    else {
+        proto_tree_add_item(tree, hf_ambit_write_data_app_data, tvb, offset, leftToRead, ENC_LITTLE_ENDIAN);
+        offset += leftToRead;
+
+        proto_tree_add_item(tree, hf_ambit_write_data_app_checksum, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+        offset += 1;
+        currentAppIndex++;
+    }
+
+    int i = currentAppIndex;
+    while (offset < length) {
+
+        uint read_len = i==0 ? apps_length[i]-1 : apps_length[i]-apps_length[i-1]-1;
+
+        if (read_len > (length-offset) ) {
+            leftToReadArray[arrayIndex+1] = read_len-(length-offset);
+            currentAppIndexArray[arrayIndex+1] = i;
+            read_len = length-offset;
+        }
+
+        proto_tree_add_item(tree, hf_ambit_write_data_app_data, tvb, offset, read_len, ENC_LITTLE_ENDIAN);
+        offset += read_len;
+
+        if (offset < length) {
+            proto_tree_add_item(tree, hf_ambit_write_data_app_checksum, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+            offset += 1;
+
+            if (offset == length) {
+                leftToReadArray[arrayIndex+1] = apps_length[i] - (length-offset);
+                currentAppIndexArray[arrayIndex+1] = i;
+            }
+        }
+
+        i++;
+    }
+}
+
+static gint dissect_ambit_data_write_content(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length)
+{
+    uint leftToRead = 0;
+
+    while (*offset < length)
+    {
+        if (*offset + 2 >= length) return *offset;
+        proto_tree_add_item(tree, hf_ambit_write_data_header, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+//        uint dataHeader = tvb_get_letohs(tvb, *offset);
+        *offset += 2;
+
+        if (*offset + 2 >= length) return *offset;
+        proto_tree_add_item(tree, hf_ambit_write_data_length, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+        uint dataLength = tvb_get_letohs(tvb, *offset);
+        *offset += 2;
+
+        uint startOffset = *offset;
+        dissect_ambit_data_write_read_data_0101(tvb, pinfo, tree, offset, length, dataLength);
+        leftToRead = dataLength - (*offset - startOffset);
+    }
+
+    return leftToRead;
+}
+
+static uint dissect_ambit_data_write_read_data_0101(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength)
+{
+    uint leftToRead = 0;
+    uint startOffset = *offset;
+
+    while (*offset < length && *offset - startOffset < packageLength)
+    {
+        if (*offset + 2 >= length) return *offset;
+        proto_tree_add_item(tree, hf_ambit_write_data_header, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+        guint16 dataHeader = tvb_get_letohs(tvb, *offset);
+        *offset += 2;
+
+        if (*offset + 2 >= length) return *offset;
+        proto_tree_add_item(tree, hf_ambit_write_data_length, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+        guint16 dataLength2 = tvb_get_letohs(tvb, *offset);
+        *offset += 2;
+
+        switch(dataHeader) {
+          case 0x0102:
+            leftToRead = dissect_ambit_data_write_read_data_0102(tvb, pinfo, tree, offset, length, dataLength2);
+            break;
+          case 0x0105:
+            leftToRead = dissect_ambit_data_write_read_data_0105(tvb, pinfo, tree, offset, length, dataLength2);
+            break;
+          case 0x010c:
+            leftToRead = dissect_ambit_data_write_read_data_010c(tvb, pinfo, tree, offset, length, dataLength2);
+            break;
+        }
+    }
+
+    return leftToRead;
+}
+
+static uint dissect_ambit_data_write_read_data_0105(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength)
+{
+    uint leftToRead = 0;
+    uint startOffset = *offset;
+    while (*offset < length && *offset - startOffset < packageLength)
+    {
+
+        if (*offset + 2 > length) return packageLength;
+        proto_tree_add_item(tree, hf_ambit_write_data_header, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+        guint16 dataHeader = tvb_get_letohs(tvb, *offset);
+        *offset += 2;
+
+        if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+        proto_tree_add_item(tree, hf_ambit_write_data_length, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+        guint16 dataLength = tvb_get_letohs(tvb, *offset);
+        *offset += 2;
+
+        switch(dataHeader) {
+          case 0x0106:
+            leftToRead = dissect_ambit_data_write_read_data_0106(tvb, pinfo, tree, offset, length, dataLength);
+            break;
+        }
+    }
+
+    return leftToRead;
+}
+
+static uint dissect_ambit_data_write_read_data_0106(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength)
+{
+    uint leftToRead = 0;
+    uint startOffset = *offset;
+    while (*offset < length && *offset - startOffset < packageLength)
+    {
+
+        if (*offset + 2 > length) return packageLength;
+        proto_tree_add_item(tree, hf_ambit_write_data_header, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+        guint16 dataHeader = tvb_get_letohs(tvb, *offset);
+        *offset += 2;
+
+        if (*offset + 2 > length)
+        {
+            return packageLength - (*offset - startOffset);
+        }
+        proto_tree_add_item(tree, hf_ambit_write_data_length, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+        guint16 dataLength = tvb_get_letohs(tvb, *offset);
+        *offset += 2;
+
+        switch(dataHeader) {
+          case 0x0107:
+            leftToRead = dissect_ambit_data_write_read_data_0107(tvb, pinfo, tree, offset, length, dataLength);
+            break;
+          case 0x0108:
+            leftToRead = dissect_ambit_data_write_read_data_0108(tvb, pinfo, tree, offset, length, dataLength);
+            break;
+        }
+    }
+
+    return leftToRead;
+}
+
+static uint dissect_ambit_data_write_read_data_0107(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength)
+{
+    uint leftToRead = 0;
+    uint startOffset = *offset;
+    while (*offset < length && *offset - startOffset < packageLength)
+    {
+
+        if (*offset + 2 > length) return packageLength;
+        proto_tree_add_item(tree, hf_ambit_write_data_display_type, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+        *offset += 2;
+
+        dissect_ambit_add_unknown(tvb, pinfo, tree, *offset, packageLength - 2);
+        *offset += packageLength - 2;
+    }
+
+    return leftToRead;
+}
+
+static uint dissect_ambit_data_write_read_data_0108(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength)
+{
+    uint leftToRead = 0;
+    uint startOffset = *offset;
+    while (*offset < length && *offset - startOffset < packageLength)
+    {
+
+        if (*offset + 2 > length) return packageLength;
+        proto_tree_add_item(tree, hf_ambit_write_data_header, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+        guint16 dataHeader = tvb_get_letohs(tvb, *offset);
+        *offset += 2;
+
+        if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+        proto_tree_add_item(tree, hf_ambit_write_data_length, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+        guint16 dataLength = tvb_get_letohs(tvb, *offset);
+        *offset += 2;
+
+        switch(dataHeader) {
+          case 0x0109:
+            leftToRead = dissect_ambit_data_write_read_data_0109(tvb, pinfo, tree, offset, length, dataLength);
+            break;
+        case 0x010a:
+          leftToRead = dissect_ambit_data_write_read_data_010a(tvb, pinfo, tree, offset, length, dataLength);
+          break;
+        }
+    }
+
+    return leftToRead;
+}
+
+static uint dissect_ambit_data_write_read_data_0109(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength)
+{
+    uint startOffset = *offset;
+
+    if (*offset + 2 > length) return packageLength;
+    proto_tree_add_item(tree, hf_ambit_log_activity_custom_mode_row, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_log_activity_custom_mode_display, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    return 0;
+}
+
+static uint dissect_ambit_data_write_read_data_010a(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength)
+{
+    if (*offset + 2 > length) return packageLength;
+    proto_tree_add_item(tree, hf_ambit_log_activity_custom_mode_view, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    return 0;
+}
+
+static uint dissect_ambit_data_get_length_to_read(guint32 *offset, guint32 length, guint16 packageLength)
+{
+    if (*offset + packageLength > length)
+    {
+        return (length - *offset);
+    }
+    return packageLength;
+}
+
+static uint dissect_ambit_data_write_read_data_010c(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength)
+{
+    uint startOffset = *offset;
+    while (*offset < length && *offset - startOffset < packageLength)
+    {
+        if (*offset + 2 > length) return packageLength;
+        proto_tree_add_item(tree, hf_ambit_write_data_header, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+        guint16 dataHeader = tvb_get_letohs(tvb, *offset);
+        *offset += 2;
+
+        if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+        proto_tree_add_item(tree, hf_ambit_write_data_length, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+        guint16 dataLength = tvb_get_letohs(tvb, *offset);
+        *offset += 2;
+
+        switch(dataHeader) {
+          case 0x010d:
+            if (*offset + dataLength > length) return packageLength - (*offset - startOffset);
+            proto_tree_add_item(tree, hf_ambit_write_data_app_index, tvb, *offset, dataLength, ENC_LITTLE_ENDIAN);
+            *offset += dataLength;
+            break;
+        }
+    }
+
+    return 0;
+}
+
+static uint dissect_ambit_data_write_read_data_0102(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /*void *data _U_,*/ guint32 *offset, guint32 length, guint16 packageLength)
+{
+    uint startOffset = *offset;
+
+    if (*offset + 16 > length) return packageLength;
+    proto_tree_add_item(tree, hf_ambit_log_header_activity_name /*hf_ambit_write_data_custom_mode_name*/, tvb, *offset, 16, ENC_LITTLE_ENDIAN);
+    *offset += 16;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_log_activity_custom_mode_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_activity_id, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    dissect_ambit_add_unknown(tvb, pinfo, tree, *offset, 2);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_use_hrbelt_and_pods, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_alti_baro_mode, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_gps_interval, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_recording_interval, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_auto_lap, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_log_header_hr_max, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_log_header_hr_min, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_use_hr_limits, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    dissect_ambit_add_unknown(tvb, pinfo, tree, *offset, 2);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_auto_pause, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_auto_scroll, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_use_interval_timer, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_interval_repetitions, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_interval_timer_time, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 6 > length) return packageLength - (*offset - startOffset);
+    dissect_ambit_add_unknown(tvb, pinfo, tree, *offset, 6);
+    *offset += 6;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_interval_timer_max, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    dissect_ambit_add_unknown(tvb, pinfo, tree, *offset, 2);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_interval_timer_time, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 6 > length) return packageLength - (*offset - startOffset);
+    dissect_ambit_add_unknown(tvb, pinfo, tree, *offset, 6);
+    *offset += 6;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_interval_timer_min, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 14 > length) return packageLength - (*offset - startOffset);
+    dissect_ambit_add_unknown(tvb, pinfo, tree, *offset, 14);
+    *offset += 14;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_backlight, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_data_display, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    if (*offset + 2 > length) return packageLength - (*offset - startOffset);
+    proto_tree_add_item(tree, hf_ambit_write_quick_navigation, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
+    *offset += 2;
+
+    return 0;
 }
 
 static gint dissect_ambit_data_write_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
@@ -2494,6 +3086,68 @@ proto_register_ambit(void)
 
         { &hf_ambit_gps_data_head,
           { "Current GPS position data version", "ambit.gps.data.head", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
+
+        { &hf_ambit_write_data_length,
+          { "Data Length", "ambit.write_data.custom_modes.length", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_header,
+          { "Data Header", "ambit.write_data.custom_modes.header", FT_UINT16, BASE_HEX, VALS(custom_modes_header_vals), 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_activity_id,
+          { "Activity ID", "ambit.write_data.custom_modes.activity_id", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_interval_repetitions,
+          { "IntervalRepetitions", "ambit.write_data.custom_modes.interval_repetitions", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_show_navigation,
+          { "Show Navigation Selection", "ambit.write_data.custom_modes.show_navigation", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_alti_baro_mode,
+          { "AltiBaroMode", "ambit.write_data.custom_modes.alti_baro_mode", FT_UINT16, BASE_DEC, VALS(custom_modes_alti_baro_mode_vals), 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_backlight,
+          { "Backlight mode", "ambit.write_data.custom_modes.alti_baro_mode", FT_UINT16, BASE_DEC, VALS(custom_modes_backlight_vals), 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_display,
+          { "Display mode", "ambit.write_data.custom_modes.alti_baro_mode", FT_UINT16, BASE_DEC, VALS(custom_modes_display_vals), 0x0,NULL, HFILL } },
+        { &hf_ambit_write_quick_navigation,
+          { "Quick navigation", "ambit.write_data.custom_modes.alti_baro_mode", FT_UINT16, BASE_DEC, VALS(custom_modes_quick_navigation_vals), 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_use_hrbelt_and_pods,
+          { "HR belt and PODs", "ambit.write_data.custom_modes.hrbelt_and_pods", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_use_hr_limits,
+          { "Use HR limits", "ambit.write_data.custom_modes.use_hr_limits", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_recording_interval,
+          { "Recording interval", "ambit.write_data.custom_modes.recording_interval", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_auto_lap,
+          { "Autolap (m)", "ambit.write_data.custom_modes.auto_lap", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_gps_interval,
+          { "GPS interval", "ambit.write_data.custom_modes.gps_interval", FT_UINT16, BASE_DEC, VALS(custom_modes_gps_accuracy_vals), 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_display_type,
+          { "Display type", "ambit.write_data.custom_modes.display_type", FT_UINT16, BASE_HEX, VALS(custom_modes_display_type_val), 0x0,NULL, HFILL } },
+        { &hf_ambit_log_activity_custom_mode_row,
+          { "            Display row", "ambit.write_data.custom_modes.display_row", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_log_activity_custom_mode_display,
+          { "            Display type", "ambit.write_data.custom_modes.display_type", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_log_activity_custom_mode_view,
+          { "            View type (lower row)", "ambit.write_data.custom_modes.view", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_auto_pause,
+          { "Auto pause", "ambit.write_data.custom_modes.auto_pause", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_auto_scroll,
+          { "Auto scroll (sec)", "ambit.write_data.custom_modes.auto_scroll", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_use_interval_timer,
+          { "Use interval timer", "ambit.write_data.custom_modes.interval_timer", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_interval_timer_time,
+          { "Interval timer unit", "ambit.write_data.custom_modes.interval_timer_time", FT_UINT16, BASE_DEC, VALS(custom_modes_interval_timer_unit_vals), 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_interval_timer_max,
+          { "Interval timer max (sec or meters)", "ambit.write_data.custom_modes.interval_timer_max", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_interval_timer_min,
+          { "Interval timer min (sec or meters)", "ambit.write_data.custom_modes.interval_timer_min", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+
+        { &hf_ambit_write_data_apps_nbr_of,
+          { "Number of apps", "ambit.write_data.apps.nbr", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_apps_header_len,
+          { "Apps header length", "ambit.write_data.apps.header_len", FT_UINT16, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_apps_end_pos,
+          { "Pos of app checksum", "ambit.write_data.apps.end_pos", FT_UINT32, BASE_HEX, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_app_data,
+          { "App data", "ambit.write_data.apps.data", FT_STRING, BASE_NONE, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_app_checksum,
+          { "App checksum (xor of app data + app data length)", "ambit.write_data.apps.checksum", FT_UINT8, BASE_DEC, NULL, 0x0,NULL, HFILL } },
+        { &hf_ambit_write_data_app_index,
+          { "App index", "ambit.write_data.apps.index", FT_STRING, BASE_NONE, NULL, 0x0,NULL, HFILL } },
     };
 
     static gint *ett[] = {
diff --git a/wireshark_dissector/tools/make-dissector-reg.py b/wireshark_dissector/tools/make-dissector-reg.py
index 4497290..71deaab 100755
--- a/wireshark_dissector/tools/make-dissector-reg.py
+++ b/wireshark_dissector/tools/make-dissector-reg.py
@@ -10,6 +10,7 @@
 # less processes would have to be started.
 #
 # $Id: make-dissector-reg.py 30447 2009-10-09 20:47:18Z krj $
+from __future__ import print_function
 
 import os
 import sys
@@ -59,7 +60,7 @@ elif registertype == "dissectors":
  */
 """
 else:
-	print "Unknown output type '%s'" % registertype
+	print("Unknown output type '%s'".format(registertype))
 	sys.exit(1)
 
 
@@ -77,7 +78,7 @@ for file in files:
 		filenames.append(os.path.join(srcdir, file))
 
 if len(filenames) < 1:
-	print "No files found"
+	print("No files found")
 	sys.exit(1)
 
 
@@ -130,7 +131,7 @@ for filename in filenames:
 	if cache and cache.has_key(filename):
 		cdict = cache[filename]
 		if cur_mtime == cdict['mtime']:
-#			print "Pulling %s from cache" % (filename)
+#			print("Pulling %s from cache" % (filename))
 			regs['proto_reg'].extend(cdict['proto_reg'])
 			regs['handoff_reg'].extend(cdict['handoff_reg'])
 			regs['wtap_register'].extend(cdict['wtap_register'])
@@ -144,7 +145,7 @@ for filename in filenames:
 			'handoff_reg': [],
 			'wtap_register': [],
 			}
-#	print "Searching %s" % (filename)
+#	print("Searching %s" % (filename))
 	for line in file.readlines():
 		for action in patterns:
 			regex = action[1]
@@ -154,7 +155,7 @@ for filename in filenames:
 				sym_type = action[0]
 				regs[sym_type].append(symbol)
 				if cache is not None:
-#					print "Caching %s for %s: %s" % (sym_type, filename, symbol)
+#					print("Caching %s for %s: %s" % (sym_type, filename, symbol))
 					cache[filename][sym_type].append(symbol)
 	file.close()
 
@@ -165,7 +166,7 @@ if cache is not None and cache_filename is not None:
 
 # Make sure we actually processed something
 if len(regs['proto_reg']) < 1:
-	print "No protocol registrations found"
+	print("No protocol registrations found")
 	sys.exit(1)
 
 # Sort the lists to make them pretty
@@ -252,7 +253,7 @@ register_wtap_module(void)
 		reg_code.write(line)
 
 	reg_code.write("}\n");
-        reg_code.write("#endif\n");
+	reg_code.write("#endif\n");
 else:
 	reg_code.write("""
 static gulong proto_reg_count(void)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-running/openambit.git



More information about the Pkg-running-devel mailing list