diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..10e3edd --- /dev/null +++ b/.travis.yml @@ -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 diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index fbaa991..7108446 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -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 \ diff --git a/doc/man/dc_descriptor_get_model.3 b/doc/man/dc_descriptor_get_model.3 new file mode 100644 index 0000000..24ee991 --- /dev/null +++ b/doc/man/dc_descriptor_get_model.3 @@ -0,0 +1,52 @@ + +.\" +.\" libdivecomputer +.\" +.\" Copyright (C) 2018 Kristaps Dzonsons +.\" +.\" 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 . diff --git a/examples/dctool_timesync.c b/examples/dctool_timesync.c index e0aff1f..35647b1 100644 --- a/examples/dctool_timesync.c +++ b/examples/dctool_timesync.c @@ -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; } diff --git a/include/libdivecomputer/iostream.h b/include/libdivecomputer/iostream.h index e2cb439..d7d2621 100644 --- a/include/libdivecomputer/iostream.h +++ b/include/libdivecomputer/iostream.h @@ -22,6 +22,7 @@ #ifndef DC_IOSTREAM_H #define DC_IOSTREAM_H +#include #include #include diff --git a/src/descriptor.c b/src/descriptor.c index 6871e1b..80fa734 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -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}, diff --git a/src/hw_ostc_parser.c b/src/hw_ostc_parser.c index f053a21..055c0f7 100644 --- a/src/hw_ostc_parser.c +++ b/src/hw_ostc_parser.c @@ -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: diff --git a/src/mares_iconhd.c b/src/mares_iconhd.c index 450245e..d5f0ede 100644 --- a/src/mares_iconhd.c +++ b/src/mares_iconhd.c @@ -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); diff --git a/src/mares_iconhd_parser.c b/src/mares_iconhd_parser.c index 0c48a22..aa44ace 100644 --- a/src/mares_iconhd_parser.c +++ b/src/mares_iconhd_parser.c @@ -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) { diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index f7a9b7a..c33c880 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -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) { diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index 444ed1e..0a2f7c2 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -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 || diff --git a/src/oceanic_common.c b/src/oceanic_common.c index 9f7341a..908896c 100644 --- a/src/oceanic_common.c +++ b/src/oceanic_common.c @@ -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; diff --git a/src/oceanic_common.h b/src/oceanic_common.h index 1b8ed08..a5c55b8 100644 --- a/src/oceanic_common.h +++ b/src/oceanic_common.h @@ -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. diff --git a/src/oceanic_veo250.c b/src/oceanic_veo250.c index 42cb676..de70c7b 100644 --- a/src/oceanic_veo250.c +++ b/src/oceanic_veo250.c @@ -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 */ diff --git a/src/oceanic_vtpro.c b/src/oceanic_vtpro.c index 2c9298b..d3387f2 100644 --- a/src/oceanic_vtpro.c +++ b/src/oceanic_vtpro.c @@ -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 */