Merge upstream libdivecomputer changes from Jef Driesen.

* https://github.com/libdivecomputer/libdivecomputer:
  Add Travis CI integration
  Fix the transport command-line parameter
  Document dc_descriptor_get_model
  Include stddef.h in iostream.h
  Add support for the Mares Smart Air
  Fix the average depth for older OSTC dives
  Add support for the Oceanic Pro Plus X
This commit is contained in:
Linus Torvalds 2018-08-31 12:52:50 -07:00
commit 63cd80c560
15 changed files with 270 additions and 47 deletions

56
.travis.yml Normal file
View File

@ -0,0 +1,56 @@
language: c
matrix:
include:
- os: linux
compiler: gcc
- os: linux
compiler: clang
- os: osx
compiler: gcc
- os: osx
compiler: clang
- os: linux
compiler: i686-w64-mingw32-gcc
addons:
apt:
packages:
- gcc-mingw-w64
- binutils-mingw-w64
- mingw-w64-tools
- os: linux
compiler: x86_64-w64-mingw32-gcc
addons:
apt:
packages:
- gcc-mingw-w64
- binutils-mingw-w64
- mingw-w64-tools
addons:
apt:
packages:
- libbluetooth-dev
- libusb-1.0-0-dev
install:
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew install hidapi libusb;
fi
script:
- case $CC in
*-gcc) TARGET="${CC%-gcc}" ;;
esac
- if [ -n "$TARGET" ]; then
TARGETOPTS="--host=${TARGET}";
unset CC;
fi
- autoreconf --install --force
- ./configure $TARGETOPTS --disable-doc
- make

View File

@ -14,6 +14,7 @@ MANPAGES = \
dc_datetime_mktime.3 \
dc_datetime_now.3 \
dc_descriptor_free.3 \
dc_descriptor_get_model.3 \
dc_descriptor_get_product.3 \
dc_descriptor_get_vendor.3 \
dc_descriptor_iterator.3 \

View File

@ -0,0 +1,52 @@
.\"
.\" libdivecomputer
.\"
.\" Copyright (C) 2018 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
.\" This library is free software; you can redistribute it and/or
.\" modify it under the terms of the GNU Lesser General Public
.\" License as published by the Free Software Foundation; either
.\" version 2.1 of the License, or (at your option) any later version.
.\"
.\" This library is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
.\" Lesser General Public License for more details.
.\"
.\" You should have received a copy of the GNU Lesser General Public
.\" License along with this library; if not, write to the Free Software
.\" Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
.\" MA 02110-1301 USA
.\"
.Dd August 19, 2018
.Dt DC_DESCRIPTOR_GET_MODEL 3
.Os
.Sh NAME
.Nm dc_descriptor_get_model
.Nd get the model of a dive computer descriptor
.Sh LIBRARY
.Lb libdivecomputer
.Sh SYNOPSIS
.In libdivecomputer/descriptor.h
.Ft "unsigned int"
.Fo dc_descriptor_get_model
.Fa "dc_descriptor_t *descriptor"
.Fc
.Sh DESCRIPTION
Gets the model number of a dive computer descriptor or 0 if none was
defined for the computer.
0 is also a valid model number.
.Sh RETURN VALUES
This returns the model number or 0 if none exists.
.Sh SEE ALSO
.Xr dc_descriptor_iterator 3
.Sh AUTHORS
The
.Lb libdivecomputer
library was written by
.An Jef Driesen ,
.Mt jef@libdivecomputer.org .
The manpages were written by
.An Kristaps Dzonsons ,
.Mt kristaps@bsd.lv .

View File

@ -123,6 +123,9 @@ dctool_timesync_run (int argc, char *argv[], dc_context_t *context, dc_descripto
case 'h':
help = 1;
break;
case 't':
transport = dctool_transport_type (optarg);
break;
default:
return EXIT_FAILURE;
}

View File

@ -22,6 +22,7 @@
#ifndef DC_IOSTREAM_H
#define DC_IOSTREAM_H
#include <stddef.h>
#include <libdivecomputer/common.h>
#include <libdivecomputer/context.h>

View File

@ -208,6 +208,7 @@ static const dc_descriptor_t g_descriptors[] = {
{"Oceanic", "OCi", DC_FAMILY_OCEANIC_ATOM2, 0x454B, DC_TRANSPORT_SERIAL, NULL},
{"Aeris", "A300CS", DC_FAMILY_OCEANIC_ATOM2, 0x454C, DC_TRANSPORT_SERIAL, NULL},
{"Beuchat", "Mundial 3", DC_FAMILY_OCEANIC_ATOM2, 0x4550, DC_TRANSPORT_SERIAL, NULL},
{"Oceanic", "Pro Plus X", DC_FAMILY_OCEANIC_ATOM2, 0x4552, DC_TRANSPORT_SERIAL, NULL},
{"Oceanic", "F10", DC_FAMILY_OCEANIC_ATOM2, 0x4553, DC_TRANSPORT_SERIAL, NULL},
{"Oceanic", "F11", DC_FAMILY_OCEANIC_ATOM2, 0x4554, DC_TRANSPORT_SERIAL, NULL},
{"Subgear", "XP-Air", DC_FAMILY_OCEANIC_ATOM2, 0x4555, DC_TRANSPORT_SERIAL, NULL},
@ -245,6 +246,7 @@ static const dc_descriptor_t g_descriptors[] = {
{"Mares", "Nemo Wide 2", DC_FAMILY_MARES_ICONHD , 0x19, DC_TRANSPORT_SERIAL, NULL},
{"Mares", "Puck 2", DC_FAMILY_MARES_ICONHD , 0x1F, DC_TRANSPORT_SERIAL, NULL},
{"Mares", "Quad Air", DC_FAMILY_MARES_ICONHD , 0x23, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, NULL},
{"Mares", "Smart Air", DC_FAMILY_MARES_ICONHD , 0x24, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, NULL},
{"Mares", "Quad", DC_FAMILY_MARES_ICONHD , 0x29, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, NULL},
/* Heinrichs Weikamp */
{"Heinrichs Weikamp", "OSTC", DC_FAMILY_HW_OSTC, 0, DC_TRANSPORT_SERIAL, NULL},

View File

@ -508,6 +508,8 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
*((double *) value) = array_uint16_le (data + layout->maxdepth) / 100.0;
break;
case DC_FIELD_AVGDEPTH:
if (parser->version < 0x21)
return DC_STATUS_UNSUPPORTED;
*((double *) value) = array_uint16_le (data + layout->avgdepth) / 100.0;
break;
case DC_FIELD_GASMIX_COUNT:

View File

@ -42,6 +42,7 @@
#define NEMOWIDE2 0x19
#define PUCK2 0x1F
#define QUADAIR 0x23
#define SMARTAIR 0x24
#define QUAD 0x29
#define ACK 0xAA
@ -127,6 +128,7 @@ mares_iconhd_get_model (mares_iconhd_device_t *device)
{"Nemo Wide 2", NEMOWIDE2},
{"Puck 2", PUCK2},
{"Quad Air", QUADAIR},
{"Smart Air", SMARTAIR},
{"Quad", QUAD},
};
@ -293,6 +295,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
device->packetsize = 256;
break;
case QUADAIR:
case SMARTAIR:
device->layout = &mares_iconhdnet_layout;
device->packetsize = 256;
break;
@ -442,7 +445,7 @@ mares_iconhd_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback,
header = 0x80;
else if (model == QUADAIR)
header = 0x84;
else if (model == SMART)
else if (model == SMART || model == SMARTAIR)
header = 4; // Type and number of samples only!
else if (model == SMARTAPNEA)
header = 6; // Type and number of samples only!
@ -504,7 +507,7 @@ mares_iconhd_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback,
// Get the number of samples in the profile data.
unsigned int type = 0, nsamples = 0;
if (model == SMART || model == SMARTAPNEA) {
if (model == SMART || model == SMARTAPNEA || model == SMARTAIR) {
type = array_uint16_le (buffer + offset - header + 2);
nsamples = array_uint16_le (buffer + offset - header + 0);
} else {
@ -541,6 +544,10 @@ mares_iconhd_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback,
headersize = 0x50;
samplesize = 14;
fingerprint = 0x40;
} else if (model == SMARTAIR) {
headersize = 0x84;
samplesize = 12;
fingerprint = 2;
}
if (offset < headersize)
break;
@ -559,7 +566,7 @@ mares_iconhd_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback,
// end of the ringbuffer. The current dive is incomplete (partially
// overwritten with newer data), and processing should stop.
unsigned int nbytes = 4 + headersize + nsamples * samplesize;
if (model == ICONHDNET || model == QUADAIR) {
if (model == ICONHDNET || model == QUADAIR || model == SMARTAIR) {
nbytes += (nsamples / 4) * 8;
} else if (model == SMARTAPNEA) {
unsigned int settings = array_uint16_le (buffer + offset - headersize + 0x1C);

View File

@ -35,6 +35,7 @@
#define ICONHD 0x14
#define ICONHDNET 0x15
#define QUADAIR 0x23
#define SMARTAIR 0x24
#define NGASMIXES 3
#define NTANKS NGASMIXES
@ -94,7 +95,7 @@ mares_iconhd_parser_cache (mares_iconhd_parser_t *parser)
header = 0x80;
else if (parser->model == QUADAIR)
header = 0x84;
else if (parser->model == SMART)
else if (parser->model == SMART || parser->model == SMARTAIR)
header = 4; // Type and number of samples only!
else if (parser->model == SMARTAPNEA)
header = 6; // Type and number of samples only!
@ -112,7 +113,7 @@ mares_iconhd_parser_cache (mares_iconhd_parser_t *parser)
// Get the number of samples in the profile data.
unsigned int type = 0, nsamples = 0;
if (parser->model == SMART || parser->model == SMARTAPNEA) {
if (parser->model == SMART || parser->model == SMARTAPNEA || parser->model == SMARTAIR) {
type = array_uint16_le (data + length - header + 2);
nsamples = array_uint16_le (data + length - header + 0);
} else {
@ -129,7 +130,7 @@ mares_iconhd_parser_cache (mares_iconhd_parser_t *parser)
if (parser->model == ICONHDNET) {
headersize = 0x80;
samplesize = 12;
} else if (parser->model == QUADAIR) {
} else if (parser->model == QUADAIR || parser->model == SMARTAIR) {
headersize = 0x84;
samplesize = 12;
} else if (parser->model == SMART) {
@ -151,7 +152,7 @@ mares_iconhd_parser_cache (mares_iconhd_parser_t *parser)
}
const unsigned char *p = data + length - headersize;
if (parser->model != SMART && parser->model != SMARTAPNEA) {
if (parser->model != SMART && parser->model != SMARTAPNEA && parser->model != SMARTAIR) {
p += 4;
}
@ -181,7 +182,7 @@ mares_iconhd_parser_cache (mares_iconhd_parser_t *parser)
// Calculate the total number of bytes for this dive.
unsigned int nbytes = 4 + headersize + nsamples * samplesize;
if (parser->model == ICONHDNET || parser->model == QUADAIR) {
if (parser->model == ICONHDNET || parser->model == QUADAIR || parser->model == SMARTAIR) {
nbytes += (nsamples / 4) * 8;
} else if (parser->model == SMARTAPNEA) {
unsigned int divetime = array_uint32_le (p + 0x24);
@ -215,7 +216,7 @@ mares_iconhd_parser_cache (mares_iconhd_parser_t *parser)
// Tanks
unsigned int ntanks = 0;
if (parser->model == ICONHDNET || parser->model == QUADAIR) {
if (parser->model == ICONHDNET || parser->model == QUADAIR || parser->model == SMARTAIR) {
unsigned int tankoffset = (parser->model == ICONHDNET) ? 0x58 : 0x5C;
while (ntanks < NTANKS) {
unsigned int beginpressure = array_uint16_le (p + tankoffset + ntanks * 4 + 0);
@ -325,6 +326,8 @@ mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime
}
} else if (parser->model == SMARTAPNEA) {
p += 0x40;
} else if (parser->model == SMARTAIR) {
p += 2;
} else {
p += 6;
}
@ -354,7 +357,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
return rc;
const unsigned char *p = abstract->data + parser->footer;
if (parser->model != SMART && parser->model != SMARTAPNEA) {
if (parser->model != SMART && parser->model != SMARTAPNEA && parser->model != SMARTAIR) {
p += 4;
}
@ -611,7 +614,8 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
nsamples++;
// Some extra data.
if ((parser->model == ICONHDNET || parser->model == QUADAIR) && (nsamples % 4) == 0) {
if ((parser->model == ICONHDNET || parser->model == QUADAIR || parser->model == SMARTAIR) &&
(nsamples % 4) == 0) {
// Pressure (1/100 bar).
unsigned int pressure = array_uint16_le(data + offset);
if (gasmix < parser->ntanks) {

View File

@ -32,6 +32,7 @@
#define ISINSTANCE(device) dc_device_isinstance((device), &oceanic_atom2_device_vtable.base)
#define PROPLUSX 0x4552
#define VTX 0x4557
#define I750TC 0x455A
@ -44,6 +45,7 @@
#define CMD_READ1 0xB1
#define CMD_READ8 0xB4
#define CMD_READ16 0xB8
#define CMD_READ16HI 0xF6
#define CMD_WRITE 0xB2
#define CMD_KEEPALIVE 0x91
#define CMD_QUIT 0x6A
@ -57,7 +59,8 @@ typedef struct oceanic_atom2_device_t {
unsigned int delay;
unsigned int bigpage;
unsigned char cache[256];
unsigned int cached;
unsigned int cached_page;
unsigned int cached_highmem;
} oceanic_atom2_device_t;
static dc_status_t oceanic_atom2_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size);
@ -184,6 +187,10 @@ static const oceanic_common_version_t oceanic_reactpro_version[] = {
{"REACPRO2 \0\0 512K"},
};
static const oceanic_common_version_t oceanic_proplusx_version[] = {
{"OCEANOCX \0\0 2048"},
};
static const oceanic_common_version_t aeris_a300cs_version[] = {
{"AER300CS \0\0 2048"},
{"OCEANVTX \0\0 2048"},
@ -196,6 +203,7 @@ static const oceanic_common_version_t aqualung_i450t_version[] = {
static const oceanic_common_layout_t aeris_f10_layout = {
0x10000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0100, /* rb_logbook_begin */
@ -210,6 +218,7 @@ static const oceanic_common_layout_t aeris_f10_layout = {
static const oceanic_common_layout_t aeris_f11_layout = {
0x20000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0100, /* rb_logbook_begin */
@ -224,6 +233,7 @@ static const oceanic_common_layout_t aeris_f11_layout = {
static const oceanic_common_layout_t oceanic_default_layout = {
0x10000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0240, /* rb_logbook_begin */
@ -238,6 +248,7 @@ static const oceanic_common_layout_t oceanic_default_layout = {
static const oceanic_common_layout_t oceanic_atom1_layout = {
0x8000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0240, /* rb_logbook_begin */
@ -252,6 +263,7 @@ static const oceanic_common_layout_t oceanic_atom1_layout = {
static const oceanic_common_layout_t oceanic_atom2a_layout = {
0xFFF0, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0240, /* rb_logbook_begin */
@ -266,6 +278,7 @@ static const oceanic_common_layout_t oceanic_atom2a_layout = {
static const oceanic_common_layout_t oceanic_atom2b_layout = {
0x10000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0240, /* rb_logbook_begin */
@ -280,6 +293,7 @@ static const oceanic_common_layout_t oceanic_atom2b_layout = {
static const oceanic_common_layout_t oceanic_atom2c_layout = {
0xFFF0, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0240, /* rb_logbook_begin */
@ -294,6 +308,7 @@ static const oceanic_common_layout_t oceanic_atom2c_layout = {
static const oceanic_common_layout_t sherwood_wisdom_layout = {
0xFFF0, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x03D0, /* rb_logbook_begin */
@ -308,6 +323,7 @@ static const oceanic_common_layout_t sherwood_wisdom_layout = {
static const oceanic_common_layout_t oceanic_proplus3_layout = {
0x10000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x03E0, /* rb_logbook_begin */
@ -322,6 +338,7 @@ static const oceanic_common_layout_t oceanic_proplus3_layout = {
static const oceanic_common_layout_t tusa_zenair_layout = {
0xFFF0, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0240, /* rb_logbook_begin */
@ -336,6 +353,7 @@ static const oceanic_common_layout_t tusa_zenair_layout = {
static const oceanic_common_layout_t oceanic_oc1_layout = {
0x20000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0240, /* rb_logbook_begin */
@ -350,6 +368,7 @@ static const oceanic_common_layout_t oceanic_oc1_layout = {
static const oceanic_common_layout_t oceanic_oci_layout = {
0x20000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x10C0, /* rb_logbook_begin */
@ -364,6 +383,7 @@ static const oceanic_common_layout_t oceanic_oci_layout = {
static const oceanic_common_layout_t oceanic_atom3_layout = {
0x20000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0400, /* rb_logbook_begin */
@ -378,6 +398,7 @@ static const oceanic_common_layout_t oceanic_atom3_layout = {
static const oceanic_common_layout_t oceanic_vt4_layout = {
0x20000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0420, /* rb_logbook_begin */
@ -392,6 +413,7 @@ static const oceanic_common_layout_t oceanic_vt4_layout = {
static const oceanic_common_layout_t hollis_tx1_layout = {
0x40000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0780, /* rb_logbook_begin */
@ -406,6 +428,7 @@ static const oceanic_common_layout_t hollis_tx1_layout = {
static const oceanic_common_layout_t oceanic_veo1_layout = {
0x0400, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0400, /* rb_logbook_begin */
@ -420,6 +443,7 @@ static const oceanic_common_layout_t oceanic_veo1_layout = {
static const oceanic_common_layout_t oceanic_reactpro_layout = {
0xFFF0, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0400, /* rb_logbook_begin */
@ -432,8 +456,24 @@ static const oceanic_common_layout_t oceanic_reactpro_layout = {
1, /* pt_mode_serial */
};
static const oceanic_common_layout_t oceanic_proplusx_layout = {
0x440000, /* memsize */
0x40000, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x1000, /* rb_logbook_begin */
0x10000, /* rb_logbook_end */
16, /* rb_logbook_entry_size */
0x40000, /* rb_profile_begin */
0x440000, /* rb_profile_end */
0, /* pt_mode_global */
1, /* pt_mode_logbook */
0, /* pt_mode_serial */
};
static const oceanic_common_layout_t aeris_a300cs_layout = {
0x40000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0900, /* rb_logbook_begin */
@ -448,6 +488,7 @@ static const oceanic_common_layout_t aeris_a300cs_layout = {
static const oceanic_common_layout_t aqualung_i450t_layout = {
0x40000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x10C0, /* rb_logbook_begin */
@ -595,12 +636,13 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, dc_iostream
device->iostream = iostream;
device->delay = 0;
device->bigpage = 1; // no big pages
device->cached = INVALID;
device->cached_page = INVALID;
device->cached_highmem = INVALID;
memset(device->cache, 0, sizeof(device->cache));
// Get the correct baudrate.
unsigned int baudrate = 38400;
if (model == VTX || model == I750TC) {
if (model == VTX || model == I750TC || model == PROPLUSX) {
baudrate = 115200;
}
@ -684,6 +726,9 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, dc_iostream
device->base.layout = &oceanic_veo1_layout;
} else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_reactpro_version)) {
device->base.layout = &oceanic_reactpro_layout;
} else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_proplusx_version)) {
device->base.layout = &oceanic_proplusx_layout;
device->bigpage = 16;
} else if (OCEANIC_COMMON_MATCH (device->base.version, aeris_a300cs_version)) {
device->base.layout = &aeris_a300cs_layout;
device->bigpage = 16;
@ -779,6 +824,7 @@ static dc_status_t
oceanic_atom2_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size)
{
oceanic_atom2_device_t *device = (oceanic_atom2_device_t*) abstract;
const oceanic_common_layout_t *layout = device->base.layout;
if ((address % PAGESIZE != 0) ||
(size % PAGESIZE != 0))
@ -807,12 +853,26 @@ oceanic_atom2_device_read (dc_device_t *abstract, unsigned int address, unsigned
// Pick the best pagesize to use.
unsigned int pagesize = device->bigpage * PAGESIZE;
// High memory state.
unsigned int highmem = 0;
unsigned int nbytes = 0;
while (nbytes < size) {
unsigned int page = address / pagesize;
if (page != device->cached) {
// Switch to the correct read command when entering the high memory area.
if (layout->highmem && address >= layout->highmem && !highmem) {
highmem = layout->highmem;
read_cmd = CMD_READ16HI;
crc_size = 2;
pagesize = 16 * PAGESIZE;
}
// Calculate the page number after mapping the virtual high memory
// addresses back to their physical address.
unsigned int page = (address - highmem) / pagesize;
if (page != device->cached_page || highmem != device->cached_highmem) {
// Read the package.
unsigned int number = page * device->bigpage; // This is always PAGESIZE, even in big page mode.
unsigned int number = highmem ? page : page * device->bigpage; // This is always PAGESIZE, even in big page mode.
unsigned char answer[256 + 2] = {0}; // Maximum we support for the known commands.
unsigned char command[4] = {read_cmd,
(number >> 8) & 0xFF, // high
@ -824,7 +884,8 @@ oceanic_atom2_device_read (dc_device_t *abstract, unsigned int address, unsigned
// Cache the page.
memcpy (device->cache, answer, pagesize);
device->cached = page;
device->cached_page = page;
device->cached_highmem = highmem;
}
unsigned int offset = address % pagesize;
@ -853,7 +914,8 @@ oceanic_atom2_device_write (dc_device_t *abstract, unsigned int address, const u
return DC_STATUS_INVALIDARGS;
// Invalidate the cache.
device->cached = INVALID;
device->cached_page = INVALID;
device->cached_highmem = INVALID;
unsigned int nbytes = 0;
while (nbytes < size) {

View File

@ -77,6 +77,7 @@
#define OCI 0x454B
#define A300CS 0x454C
#define MUNDIAL3 0x4550
#define PROPLUSX 0x4552
#define F10B 0x4553
#define F11B 0x4554
#define XPAIR 0x4555
@ -177,6 +178,8 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
} else if (model == A300CS || model == VTX ||
model == I450T || model == I750TC) {
parser->headersize = 5 * PAGESIZE;
} else if (model == PROPLUSX) {
parser->headersize = 3 * PAGESIZE;
}
parser->serial = serial;
@ -313,6 +316,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim
case VTX:
case I450T:
case I750TC:
case PROPLUSX:
datetime->year = (p[10]) + 2000;
datetime->month = (p[8]);
datetime->day = (p[9]);
@ -641,7 +645,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
if (parser->mode != FREEDIVE) {
unsigned int idx = 0x17;
if (parser->model == A300CS || parser->model == VTX ||
parser->model == I450T || parser->model == I750TC)
parser->model == I450T || parser->model == I750TC ||
parser->model == PROPLUSX)
idx = 0x1f;
switch (data[idx] & 0x03) {
case 0:
@ -696,7 +701,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
parser->model == OC1C || parser->model == OCI ||
parser->model == TX1 || parser->model == A300CS ||
parser->model == VTX || parser->model == I450T ||
parser->model == I750TC) {
parser->model == I750TC || parser->model == PROPLUSX) {
samplesize = PAGESIZE;
}
@ -874,7 +879,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
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 ||
parser->model == I750TC) {
parser->model == I750TC || parser->model == PROPLUSX) {
temperature = data[offset + 11];
} else {
unsigned int sign;
@ -914,7 +919,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
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 || parser->model == I750TC)
parser->model == VTX || parser->model == I750TC ||
parser->model == PROPLUSX)
pressure = array_uint16_le (data + offset + 4);
else
pressure -= data[offset + 1];
@ -962,7 +968,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
unsigned int have_deco = 0;
unsigned int decostop = 0, decotime = 0;
if (parser->model == A300CS || parser->model == VTX ||
parser->model == I450T || parser->model == I750TC) {
parser->model == I450T || parser->model == I750TC ||
parser->model == PROPLUSX) {
decostop = (data[offset + 15] & 0x70) >> 4;
decotime = array_uint16_le(data + offset + 6) & 0x03FF;
have_deco = 1;
@ -1005,7 +1012,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
have_rbt = 1;
} else if (parser->model == I450T || parser->model == OC1A ||
parser->model == OC1B || parser->model == OC1C ||
parser->model == OCI) {
parser->model == OCI || parser->model == PROPLUSX) {
rbt = array_uint16_le(data + offset + 8) & 0x01FF;
have_rbt = 1;
} else if (parser->model == VISION || parser->model == XPAIR ||

View File

@ -41,7 +41,7 @@
#define INVALID 0
static unsigned int
get_profile_first (const unsigned char data[], const oceanic_common_layout_t *layout)
get_profile_first (const unsigned char data[], const oceanic_common_layout_t *layout, unsigned int pagesize)
{
unsigned int value;
@ -55,17 +55,22 @@ get_profile_first (const unsigned char data[], const oceanic_common_layout_t *la
return array_uint16_le (data + 16);
}
if (layout->memsize > 0x20000)
return (value & 0x3FFF) * PAGESIZE;
else if (layout->memsize > 0x10000)
return (value & 0x1FFF) * PAGESIZE;
else
return (value & 0x0FFF) * PAGESIZE;
unsigned int npages = (layout->memsize - layout->highmem) / pagesize;
if (npages > 0x2000) {
value &= 0x3FFF;
} else if (npages > 0x1000) {
value &= 0x1FFF;
} else {
value &= 0x0FFF;
}
return layout->highmem + value * pagesize;
}
static unsigned int
get_profile_last (const unsigned char data[], const oceanic_common_layout_t *layout)
get_profile_last (const unsigned char data[], const oceanic_common_layout_t *layout, unsigned int pagesize)
{
unsigned int value;
@ -79,12 +84,17 @@ get_profile_last (const unsigned char data[], const oceanic_common_layout_t *lay
return array_uint16_le(data + 18);
}
if (layout->memsize > 0x20000)
return (value & 0x3FFF) * PAGESIZE;
else if (layout->memsize > 0x10000)
return (value & 0x1FFF) * PAGESIZE;
else
return (value & 0x0FFF) * PAGESIZE;
unsigned int npages = (layout->memsize - layout->highmem) / pagesize;
if (npages > 0x2000) {
value &= 0x3FFF;
} else if (npages > 0x1000) {
value &= 0x1FFF;
} else {
value &= 0x0FFF;
}
return layout->highmem + value * pagesize;
}
@ -330,6 +340,9 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
const oceanic_common_layout_t *layout = device->layout;
// Get the pagesize
unsigned int pagesize = layout->highmem ? 16 * PAGESIZE : PAGESIZE;
// Cache the logbook pointer and size.
const unsigned char *logbooks = dc_buffer_get_data (logbook);
unsigned int rb_logbook_size = dc_buffer_get_size (logbook);
@ -352,8 +365,8 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
entry -= layout->rb_logbook_entry_size;
// Get the profile pointers.
unsigned int rb_entry_first = get_profile_first (logbooks + entry, layout);
unsigned int rb_entry_last = get_profile_last (logbooks + entry, layout);
unsigned int rb_entry_first = get_profile_first (logbooks + entry, layout, pagesize);
unsigned int rb_entry_last = get_profile_last (logbooks + entry, layout, pagesize);
if (rb_entry_first < layout->rb_profile_begin ||
rb_entry_first >= layout->rb_profile_end ||
rb_entry_last < layout->rb_profile_begin ||
@ -365,8 +378,8 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
}
// Calculate the end pointer and the number of bytes.
unsigned int rb_entry_end = RB_PROFILE_INCR (rb_entry_last, PAGESIZE, layout);
unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_first, rb_entry_last, layout) + PAGESIZE;
unsigned int rb_entry_end = RB_PROFILE_INCR (rb_entry_last, pagesize, layout);
unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_first, rb_entry_last, layout) + pagesize;
// Take the end pointer of the most recent logbook entry as the
// end of profile pointer.
@ -430,8 +443,8 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
entry -= layout->rb_logbook_entry_size;
// Get the profile pointers.
unsigned int rb_entry_first = get_profile_first (logbooks + entry, layout);
unsigned int rb_entry_last = get_profile_last (logbooks + entry, layout);
unsigned int rb_entry_first = get_profile_first (logbooks + entry, layout, pagesize);
unsigned int rb_entry_last = get_profile_last (logbooks + entry, layout, pagesize);
if (rb_entry_first < layout->rb_profile_begin ||
rb_entry_first >= layout->rb_profile_end ||
rb_entry_last < layout->rb_profile_begin ||
@ -445,8 +458,8 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
}
// Calculate the end pointer and the number of bytes.
unsigned int rb_entry_end = RB_PROFILE_INCR (rb_entry_last, PAGESIZE, layout);
unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_first, rb_entry_last, layout) + PAGESIZE;
unsigned int rb_entry_end = RB_PROFILE_INCR (rb_entry_last, pagesize, layout);
unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_first, rb_entry_last, layout) + pagesize;
// Skip gaps between the profiles.
unsigned int gap = 0;
@ -481,6 +494,14 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
offset -= layout->rb_logbook_entry_size;
memcpy (profiles + offset, logbooks + entry, layout->rb_logbook_entry_size);
// Remove padding from the profile.
if (layout->highmem) {
unsigned char *profile = profiles + offset + layout->rb_logbook_entry_size;
while (rb_entry_size >= PAGESIZE && array_isequal (profile + rb_entry_size - PAGESIZE, PAGESIZE, 0xFF)) {
rb_entry_size -= PAGESIZE;
}
}
unsigned char *p = profiles + offset;
if (callback && !callback (p, rb_entry_size + layout->rb_logbook_entry_size, p, layout->rb_logbook_entry_size, userdata)) {
break;

View File

@ -38,6 +38,7 @@ extern "C" {
typedef struct oceanic_common_layout_t {
// Memory size.
unsigned int memsize;
unsigned int highmem;
// Device info.
unsigned int cf_devinfo;
// Ringbuffer pointers.

View File

@ -75,6 +75,7 @@ static const oceanic_common_version_t oceanic_veo250_version[] = {
static const oceanic_common_layout_t oceanic_veo250_layout = {
0x8000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0400, /* rb_logbook_begin */

View File

@ -89,6 +89,7 @@ static const oceanic_common_version_t oceanic_wisdom_version[] = {
static const oceanic_common_layout_t oceanic_vtpro_layout = {
0x8000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0240, /* rb_logbook_begin */
@ -103,6 +104,7 @@ static const oceanic_common_layout_t oceanic_vtpro_layout = {
static const oceanic_common_layout_t oceanic_wisdom_layout = {
0x8000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x03D0, /* rb_logbook_begin */
@ -117,6 +119,7 @@ static const oceanic_common_layout_t oceanic_wisdom_layout = {
static const oceanic_common_layout_t aeris_500ai_layout = {
0x20000, /* memsize */
0, /* highmem */
0x0000, /* cf_devinfo */
0x0110, /* cf_pointers */
0x0200, /* rb_logbook_begin */