diff --git a/NEWS b/NEWS
index ec4d0ce..938041d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,54 @@
+Version 0.5.0 (2016-09-30)
+==========================
+
+After more than three years of development, the v0.5.0 release is long
+overdue. The main highlights are the support for many new devices, a few
+new features and lots of bug fixes. This release is fully backwards
+compatible with the previous one.
+
+New features:
+
+ * Add support for new backends:
+ - aqualand: Citizen Hyper Aqualand
+ - commander: Cochran Commander and EMC
+ - eonsteel: Suunto EON Steel
+ - idive: DiveSystem iDive and iX3M
+ - meridian: Scubapro Meridian, Mantis and Chromis
+ - nitekq: Dive Rite NiTek Q
+ * Add support for many new devices:
+ - Aeris: 500 AI, A300, A300CS, F11, XR-1 NX
+ - Aqualung: i300, i450T, i550T
+ - Beuchat: Mundial 2, Mundial 3, Voyager 2G
+ - Cressi: Giotto, Newton
+ - Dive Rite: NiTek Trio
+ - Heinrichs Weikamp: OSTC 2, 3+, 4, cR and Sport
+ - Hollis: TX1
+ - Mares: Airlab, Smart, Smart Apnea, Puck 2
+ - Oceanic: F11, OCi, VTX
+ - Scubapro: XTender 5
+ - Shearwater: Nerd, Perdix, Petrel 2
+ - Sherwood: Amphos, Amphos Air, Vision
+ - Subgear: XP-3G, XP-Air
+ - Suunto: Vyper Novo, Zoop Novo
+ - Tusa: IQ-700
+ - Uwatec: Aladin 2G, Aladin Sport
+ * Add a new sample with the active gas mix.
+ * Add the temperature, tank and divemode fields.
+ * Add support for updating the OSTC and OSTC3 firmware.
+ * Add support for configuring the OSTC3 settings.
+ * Add a new dc_parser_new2 convenience function.
+
+Removed/changed features:
+
+ * The gas change events (SAMPLE_EVENT_GASCHANGE and
+ SAMPLE_EVENT_GASCHANGE2) have been replaced with the new gasmix
+ sample (DC_SAMPLE_GASMIX). The legacy events are considered
+ deprecated, but kept for backwards compatibility.
+
+Bug fixes:
+
+ * Many small improvements
+
Version 0.4.0 (2013-05-13)
==========================
diff --git a/include/libdivecomputer/Makefile.am b/include/libdivecomputer/Makefile.am
index 56afd44..ad06441 100644
--- a/include/libdivecomputer/Makefile.am
+++ b/include/libdivecomputer/Makefile.am
@@ -14,6 +14,7 @@ libdivecomputer_HEADERS = \
suunto.h \
suunto_solution.h \
suunto_eon.h \
+ suunto_eonsteel.h \
suunto_vyper.h \
suunto_vyper2.h \
suunto_d9.h \
diff --git a/msvc/libdivecomputer.vcproj b/msvc/libdivecomputer.vcproj
index 52781f2..2f3dcdf 100644
--- a/msvc/libdivecomputer.vcproj
+++ b/msvc/libdivecomputer.vcproj
@@ -462,6 +462,10 @@
RelativePath="..\src\suunto_vyper_parser.c"
>
+
+
@@ -752,6 +756,10 @@
RelativePath="..\include\libdivecomputer\units.h"
>
+
+
diff --git a/src/Makefile.am b/src/Makefile.am
index fba41a8..f3305a4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -65,7 +65,7 @@ libdivecomputer_la_SOURCES = \
checksum.h checksum.c \
array.h array.c \
buffer.c \
- cochran_commander.h cochran_commander.c \
+ cochran_commander.c \
cochran_commander_parser.c
if OS_WIN32
diff --git a/src/descriptor.c b/src/descriptor.c
index 0646f2f..4a1652f 100644
--- a/src/descriptor.c
+++ b/src/descriptor.c
@@ -195,6 +195,7 @@ static const dc_descriptor_t g_descriptors[] = {
{"Aeris", "A300CS", DC_FAMILY_OCEANIC_ATOM2, 0x454C},
{"Beuchat", "Mundial 3", DC_FAMILY_OCEANIC_ATOM2, 0x4550},
{"Oceanic", "F11", DC_FAMILY_OCEANIC_ATOM2, 0x4554},
+ {"Subgear", "XP-Air", DC_FAMILY_OCEANIC_ATOM2, 0x4555},
{"Sherwood", "Vision", DC_FAMILY_OCEANIC_ATOM2, 0x4556},
{"Oceanic", "VTX", DC_FAMILY_OCEANIC_ATOM2, 0x4557},
{"Aqualung", "i300", DC_FAMILY_OCEANIC_ATOM2, 0x4559},
diff --git a/src/hw_ostc_parser.c b/src/hw_ostc_parser.c
index c230c35..da21fb0 100644
--- a/src/hw_ostc_parser.c
+++ b/src/hw_ostc_parser.c
@@ -28,6 +28,7 @@
#endif
#include
+#include
#include "libdivecomputer/units.h"
#include "context-private.h"
diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c
index b3ddce4..7acb958 100644
--- a/src/oceanic_atom2.c
+++ b/src/oceanic_atom2.c
@@ -163,6 +163,7 @@ static const oceanic_common_version_t oceanic_vt4_version[] = {
{"OCEAVT41 \0\0 1024"},
{"AERISAIR \0\0 1024"},
{"SWVISION \0\0 1024"},
+ {"XPSUBAIR \0\0 1024"},
};
static const oceanic_common_version_t hollis_tx1_version[] = {
diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c
index dbf0859..7c255cc 100644
--- a/src/oceanic_atom2_parser.c
+++ b/src/oceanic_atom2_parser.c
@@ -78,6 +78,7 @@
#define A300CS 0x454C
#define MUNDIAL3 0x4550
#define F11B 0x4554
+#define XPAIR 0x4555
#define VISION 0x4556
#define VTX 0x4557
#define I300 0x4559
@@ -246,6 +247,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim
case OCI:
case I550T:
case VISION:
+ case XPAIR:
datetime->year = ((p[5] & 0xE0) >> 5) + ((p[7] & 0xE0) >> 2) + 2000;
datetime->month = (p[3] & 0x0F);
datetime->day = ((p[0] & 0x80) >> 3) + ((p[3] & 0xF0) >> 4);
@@ -380,7 +382,8 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
unsigned int header = headersize - PAGESIZE / 2;
unsigned int footer = size - footersize;
if (parser->model == VT4 || parser->model == VT41 ||
- parser->model == A300AI || parser->model == VISION) {
+ parser->model == A300AI || parser->model == VISION ||
+ parser->model == XPAIR) {
header = 3 * PAGESIZE;
}
@@ -407,7 +410,8 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
ngasmixes = 1;
o2_offset = header + 3;
} else if (parser->model == VT4 || parser->model == VT41 ||
- parser->model == A300AI || parser->model == VISION) {
+ parser->model == A300AI || parser->model == VISION ||
+ parser->model == XPAIR) {
o2_offset = header + 4;
ngasmixes = 4;
} else if (parser->model == OCI) {
@@ -771,7 +775,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
temperature = data[offset + 1];
} else if (parser->model == VT4 || parser->model == VT41 ||
parser->model == ATOM3 || parser->model == ATOM31 ||
- parser->model == A300AI || parser->model == VISION) {
+ parser->model == A300AI || parser->model == VISION ||
+ parser->model == XPAIR) {
temperature = ((data[offset + 7] & 0xF0) >> 4) | ((data[offset + 7] & 0x0C) << 2) | ((data[offset + 5] & 0x0C) << 4);
} else if (parser->model == A300CS || parser->model == VTX) {
temperature = data[offset + 11];
@@ -810,7 +815,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
parser->model == ZENAIR ||parser->model == A300AI ||
parser->model == DG03 || parser->model == PROPLUS3 ||
parser->model == AMPHOSAIR || parser->model == I550T ||
- parser->model == VISION)
+ parser->model == VISION || parser->model == XPAIR)
pressure = (((data[offset + 0] & 0x03) << 8) + data[offset + 1]) * 5;
else if (parser->model == TX1 || parser->model == A300CS || parser->model == VTX)
pressure = array_uint16_le (data + offset + 4);
@@ -879,7 +884,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
decostop = data[offset + 10];
decotime = array_uint16_le(data + offset + 6);
have_deco = 1;
- } else if (parser->model == ATOM31 || parser->model == VISION) {
+ } else if (parser->model == ATOM31 || parser->model == VISION ||
+ parser->model == XPAIR) {
decostop = (data[offset + 5] & 0xF0) >> 4;
decotime = array_uint16_le(data + offset + 4) & 0x03FF;
have_deco = 1;
@@ -911,7 +917,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
} else if (parser->model == I550T) {
rbt = array_uint16_le(data + offset + 4) & 0x03FF;
have_rbt = 1;
- } else if (parser->model == VISION) {
+ } else if (parser->model == VISION || parser->model == XPAIR) {
rbt = array_uint16_le(data + offset + 6) & 0x03FF;
have_rbt = 1;
}
diff --git a/src/suunto_eonsteel_parser.c b/src/suunto_eonsteel_parser.c
index 4537b66..5746085 100644
--- a/src/suunto_eonsteel_parser.c
+++ b/src/suunto_eonsteel_parser.c
@@ -38,6 +38,16 @@
#include "parser-private.h"
#include "array.h"
+#ifdef _MSC_VER
+#define strcasecmp _stricmp
+#if _MSC_VER < 1800
+// The rint() function is only available in MSVC 2013 and later
+// versions. Our replacement macro isn't entirely correct, because the
+// rounding rules for halfway cases are slightly different (away from
+// zero vs to even). But for our use-case, that's not a problem.
+#define rint(x) ((x) >= 0.0 ? floor((x) + 0.5): ceil((x) - 0.5))
+#endif
+#endif
#define C_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
@@ -664,7 +674,7 @@ static const char *lookup_enum(const struct type_desc *desc, unsigned char value
if (n != value)
continue;
- ret = malloc(end - begin + 1);
+ ret = (char *)malloc(end - begin + 1);
if (!ret)
break;
@@ -1125,7 +1135,7 @@ static int add_gas_type(suunto_eonsteel_parser_t *eon, const struct type_desc *d
else if (!strcasecmp(name, "Oxygen"))
tankinfo |= DC_TANKINFO_CC_O2;
else if (!strcasecmp(name, "None"))
- tankinfo = 0;
+ tankinfo = DC_TANKVOLUME_NONE;
else if (strcasecmp(name, "Primary"))
DEBUG(eon->base.context, "Unknown gas type %u (%s)", type, name);
@@ -1358,7 +1368,7 @@ static int traverse_diving_fields(suunto_eonsteel_parser_t *eon, const struct ty
return add_string(eon, "Deco algorithm", data);
if (!strcmp(name, "DiveMode")) {
- if (!strncmp(data, "CCR", 3)) {
+ if (!strncmp((const char *)data, "CCR", 3)) {
eon->cache.divemode = DC_DIVEMODE_CC;
eon->cache.initialized |= 1 << DC_FIELD_DIVEMODE;
}