diff --git a/contrib/android/Android.mk b/contrib/android/Android.mk index 43f5473..5c1c6f9 100644 --- a/contrib/android/Android.mk +++ b/contrib/android/Android.mk @@ -71,6 +71,7 @@ LOCAL_SRC_FILES := \ src/oceans_s1_parser.c \ src/packet.c \ src/parser.c \ + src/pelagic_i330r.c \ src/platform.c \ src/rbstream.c \ src/reefnet_sensus.c \ diff --git a/contrib/msvc/libdivecomputer.vcxproj b/contrib/msvc/libdivecomputer.vcxproj index 704ef8b..991f1ac 100644 --- a/contrib/msvc/libdivecomputer.vcxproj +++ b/contrib/msvc/libdivecomputer.vcxproj @@ -239,6 +239,7 @@ + @@ -357,6 +358,7 @@ + diff --git a/examples/common.c b/examples/common.c index f30337b..4f965f1 100644 --- a/examples/common.c +++ b/examples/common.c @@ -72,6 +72,7 @@ static const backend_table_t g_backends[] = { {"vtpro", DC_FAMILY_OCEANIC_VTPRO, 0x4245}, {"veo250", DC_FAMILY_OCEANIC_VEO250, 0x424C}, {"atom2", DC_FAMILY_OCEANIC_ATOM2, 0x4342}, + {"i330r", DC_FAMILY_PELAGIC_I330R, 0x4744}, {"nemo", DC_FAMILY_MARES_NEMO, 0}, {"puck", DC_FAMILY_MARES_PUCK, 7}, {"darwin", DC_FAMILY_MARES_DARWIN, 0}, diff --git a/include/libdivecomputer/common.h b/include/libdivecomputer/common.h index 0d5ab17..0ec8a9f 100644 --- a/include/libdivecomputer/common.h +++ b/include/libdivecomputer/common.h @@ -78,6 +78,7 @@ typedef enum dc_family_t { DC_FAMILY_OCEANIC_VTPRO = (4 << 16), DC_FAMILY_OCEANIC_VEO250, DC_FAMILY_OCEANIC_ATOM2, + DC_FAMILY_PELAGIC_I330R, /* Mares */ DC_FAMILY_MARES_NEMO = (5 << 16), DC_FAMILY_MARES_PUCK, diff --git a/src/Makefile.am b/src/Makefile.am index 2139959..495d25e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,6 +43,7 @@ libdivecomputer_la_SOURCES = \ oceanic_atom2.h oceanic_atom2.c oceanic_atom2_parser.c \ oceanic_veo250.h oceanic_veo250.c oceanic_veo250_parser.c \ oceanic_vtpro.h oceanic_vtpro.c oceanic_vtpro_parser.c \ + pelagic_i330r.h pelagic_i330r.c \ mares_common.h mares_common.c \ mares_nemo.h mares_nemo.c mares_nemo_parser.c \ mares_puck.h mares_puck.c \ diff --git a/src/descriptor.c b/src/descriptor.c index f23c93d..0b72a5a 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -275,6 +275,9 @@ static const dc_descriptor_t g_descriptors[] = { {"Aqualung", "i470TC", DC_FAMILY_OCEANIC_ATOM2, 0x4743, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic}, {"Aqualung", "i200Cv2", DC_FAMILY_OCEANIC_ATOM2, 0x4749, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic}, {"Oceanic", "Geo Air", DC_FAMILY_OCEANIC_ATOM2, 0x474B, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic}, + /* Pelagic I330R */ + {"Apeks", "DSX", DC_FAMILY_PELAGIC_I330R, 0x4741, DC_TRANSPORT_BLE, dc_filter_oceanic}, + {"Aqualung", "i330R", DC_FAMILY_PELAGIC_I330R, 0x4744, DC_TRANSPORT_BLE, dc_filter_oceanic}, /* Mares Nemo */ {"Mares", "Nemo", DC_FAMILY_MARES_NEMO, 0, DC_TRANSPORT_SERIAL, NULL}, {"Mares", "Nemo Steel", DC_FAMILY_MARES_NEMO, 0, DC_TRANSPORT_SERIAL, NULL}, @@ -755,8 +758,10 @@ dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const 0x4654, // Oceanic Veo 4.0 0x4655, // Sherwood Wisdom 4 0x4656, // Oceanic Pro Plus 4 + 0x4741, // Apeks DSX 0x4742, // Sherwood Beacon 0x4743, // Aqualung i470TC + 0x4744, // Aqualung i330R 0x4749, // Aqualung i200C (newer model) 0x474B, // Oceanic Geo Air }; diff --git a/src/device.c b/src/device.c index 6443159..f7d0c43 100644 --- a/src/device.c +++ b/src/device.c @@ -38,6 +38,7 @@ #include "oceanic_atom2.h" #include "oceanic_veo250.h" #include "oceanic_vtpro.h" +#include "pelagic_i330r.h" #include "mares_darwin.h" #include "mares_iconhd.h" #include "mares_nemo.h" @@ -165,6 +166,9 @@ dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descr case DC_FAMILY_OCEANIC_ATOM2: rc = oceanic_atom2_device_open (&device, context, iostream, dc_descriptor_get_model (descriptor)); break; + case DC_FAMILY_PELAGIC_I330R: + rc = pelagic_i330r_device_open (&device, context, iostream, dc_descriptor_get_model (descriptor)); + break; case DC_FAMILY_MARES_NEMO: rc = mares_nemo_device_open (&device, context, iostream); break; diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index fe50796..9443e63 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -37,6 +37,12 @@ #define GAUGE 1 #define FREEDIVE 2 +#define DSX_CC 0 +#define DSX_OC 1 +#define DSX_SIDEMOUNT 2 +#define DSX_SIDEGAUGE 3 +#define DSX_GAUGE 4 + #define NGASMIXES 6 #define HEADER 1 @@ -47,6 +53,7 @@ typedef struct oceanic_atom2_parser_t oceanic_atom2_parser_t; struct oceanic_atom2_parser_t { dc_parser_t base; unsigned int model; + unsigned int logbooksize; unsigned int headersize; unsigned int footersize; unsigned int serial; @@ -96,6 +103,7 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, const uns // Set the default values. parser->model = model; + parser->logbooksize = 0; parser->headersize = 9 * PAGESIZE / 2; parser->footersize = 2 * PAGESIZE / 2; if (model == DATAMASK || model == COMPUMASK || @@ -134,6 +142,14 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, const uns } else if (model == I550C || model == WISDOM4 || model == I200CV2) { parser->headersize = 5 * PAGESIZE / 2; + } else if (model == I330R) { + parser->logbooksize = 64; + parser->headersize = parser->logbooksize + 80; + parser->footersize = 48; + } else if (model == DSX) { + parser->logbooksize = 512; + parser->headersize = parser->logbooksize + 256; + parser->footersize = 64; } parser->serial = serial; @@ -174,8 +190,18 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim if (datetime) { // AM/PM bit of the 12-hour clock. unsigned int pm = p[1] & 0x80; + unsigned int have_ampm = 1; switch (parser->model) { + case I330R: + case DSX: + datetime->year = p[7] + 2000; + datetime->month = p[6]; + datetime->day = p[5]; + datetime->hour = p[3]; + datetime->minute = p[4]; + have_ampm = 0; + break; case OC1A: case OC1B: case OC1C: @@ -284,9 +310,11 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim datetime->timezone = DC_TIMEZONE_NONE; // Convert to a 24-hour clock. - datetime->hour %= 12; - if (pm) - datetime->hour += 12; + if (have_ampm) { + datetime->hour %= 12; + if (pm) + datetime->hour += 12; + } /* * Workaround for the year 2010 problem. @@ -362,6 +390,10 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser) } else if (parser->model == VEO20 || parser->model == VEO30 || parser->model == OCS) { mode = (data[1] & 0x60) >> 5; + } else if (parser->model == I330R) { + mode = data[2]; + } else if (parser->model == DSX) { + mode = data[45]; } // Get the gas mixes. @@ -419,6 +451,17 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser) } else if (parser->model == WISDOM4) { o2_offset = header + 4; ngasmixes = 1; + } else if (parser->model == I330R) { + ngasmixes = 3; + o2_offset = parser->logbooksize + 16; + } else if (parser->model == DSX) { + if (mode < DSX_SIDEGAUGE) { + o2_offset = parser->logbooksize + 0x89 + mode * 16; + he_offset = parser->logbooksize + 0xB9 + mode * 16; + ngasmixes = 6; + } else { + ngasmixes = 0; + } } else { o2_offset = header + 4; ngasmixes = 3; @@ -432,6 +475,10 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser) for (unsigned int i = 0; i < ngasmixes; ++i) { if (data[o2_offset + i * o2_step]) { parser->oxygen[i] = data[o2_offset + i * o2_step]; + // The i330R uses 20 as "Air" and 21 as 21% Nitrox + if (parser->model == I330R && parser->oxygen[i] == 20) { + parser->oxygen[i] = 21; + } } else { parser->oxygen[i] = 21; } @@ -493,9 +540,18 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns parser->model == F11A || parser->model == F11B || parser->model == MUNDIAL2 || parser->model == MUNDIAL3) *((double *) value) = array_uint16_le (data + 4) / 16.0 * FEET; + else if (parser->model == I330R || parser->model == DSX) + *((double *) value) = array_uint16_le (data + parser->footer + 10) / 10.0 * FEET; else *((double *) value) = (array_uint16_le (data + parser->footer + 4) & 0x0FFF) / 16.0 * FEET; break; + case DC_FIELD_AVGDEPTH: + if (parser->model == I330R || parser->model == DSX) { + *((double *) value) = array_uint16_le (data + parser->footer + 12) / 10.0 * FEET; + } else { + return DC_STATUS_UNSUPPORTED; + } + break; case DC_FIELD_GASMIX_COUNT: *((unsigned int *) value) = parser->ngasmixes; break; @@ -514,23 +570,49 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns water->type = DC_WATER_SALT; } water->density = 0.0; + } else if (parser->model == I330R || parser->model == DSX) { + unsigned int settings = array_uint32_le (data + parser->logbooksize + 12); + if (settings & 0x10000) { + water->type = DC_WATER_FRESH; + } else { + water->type = DC_WATER_SALT; + } + water->density = 0.0; } else { return DC_STATUS_UNSUPPORTED; } break; case DC_FIELD_DIVEMODE: - switch (parser->mode) { - case NORMAL: - *((unsigned int *) value) = DC_DIVEMODE_OC; - break; - case GAUGE: - *((unsigned int *) value) = DC_DIVEMODE_GAUGE; - break; - case FREEDIVE: - *((unsigned int *) value) = DC_DIVEMODE_FREEDIVE; - break; - default: - return DC_STATUS_DATAFORMAT; + if (parser->model == DSX) { + switch (parser->mode) { + case DSX_OC: + case DSX_SIDEMOUNT: + *((unsigned int *) value) = DC_DIVEMODE_OC; + break; + case DSX_SIDEGAUGE: + case DSX_GAUGE: + *((unsigned int *) value) = DC_DIVEMODE_GAUGE; + break; + case DSX_CC: + *((unsigned int *) value) = DC_DIVEMODE_CCR; + break; + default: + return DC_STATUS_DATAFORMAT; + } + } else { + switch (parser->mode) { + case NORMAL: + *((unsigned int *) value) = DC_DIVEMODE_OC; + break; + case GAUGE: + *((unsigned int *) value) = DC_DIVEMODE_GAUGE; + break; + case FREEDIVE: + *((unsigned int *) value) = DC_DIVEMODE_FREEDIVE; + break; + default: + return DC_STATUS_DATAFORMAT; + } } break; case DC_FIELD_STRING: @@ -606,15 +688,19 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ unsigned int time = 0; unsigned int interval = 1000; if (parser->mode != FREEDIVE) { - unsigned int offset = 0x17; - if (parser->model == A300CS || parser->model == VTX || - parser->model == I450T || parser->model == I750TC || - parser->model == PROPLUSX || parser->model == I770R || - parser->model == SAGE || parser->model == BEACON) - offset = 0x1f; - const unsigned int intervals[] = {2000, 15000, 30000, 60000}; - unsigned int idx = data[offset] & 0x03; - interval = intervals[idx]; + if (parser->model == I330R || parser->model == DSX) { + interval = data[parser->logbooksize + 36] * 1000; + } else { + unsigned int offset = 0x17; + if (parser->model == A300CS || parser->model == VTX || + parser->model == I450T || parser->model == I750TC || + parser->model == PROPLUSX || parser->model == I770R || + parser->model == SAGE || parser->model == BEACON) + offset = 0x1f; + const unsigned int intervals[] = {2000, 15000, 30000, 60000}; + unsigned int idx = data[offset] & 0x03; + interval = intervals[idx]; + } } else if (parser->model == F11A || parser->model == F11B) { const unsigned int intervals[] = {250, 500, 1000, 2000}; unsigned int idx = data[0x29] & 0x03; @@ -637,8 +723,10 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ parser->model == I750TC || parser->model == PROPLUSX || parser->model == I770R || parser->model == I470TC || parser->model == SAGE || parser->model == BEACON || - parser->model == GEOAIR) { + parser->model == GEOAIR || parser->model == I330R) { samplesize = PAGESIZE; + } else if (parser->model == DSX) { + samplesize = 32; } unsigned int have_temperature = 1, have_pressure = 1; @@ -653,7 +741,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ parser->model == I200 || parser->model == I100 || parser->model == I300C || parser->model == TALIS || parser->model == I200C || parser->model == I200CV2 || - parser->model == GEO40 || parser->model == VEO40) { + parser->model == GEO40 || parser->model == VEO40 || + parser->model == I330R) { have_pressure = 0; } @@ -822,6 +911,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ parser->model == I770R|| parser->model == SAGE || parser->model == BEACON) { temperature = data[offset + 11]; + } else if (parser->model == I330R || parser->model == DSX) { + temperature = array_uint16_le(data + offset + 10); } else { unsigned int sign; if (parser->model == DG03 || parser->model == PROPLUS3 || @@ -844,7 +935,11 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ else temperature += (data[offset + 7] & 0x0C) >> 2; } - sample.temperature = (temperature - 32.0) * (5.0 / 9.0); + if (parser->model == I330R || parser->model == DSX) { + sample.temperature = ((temperature / 10.0) - 32.0) * (5.0 / 9.0); + } else { + sample.temperature = (temperature - 32.0) * (5.0 / 9.0); + } if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata); } @@ -869,8 +964,12 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ parser->model == PROPLUSX || parser->model == I770R || parser->model == SAGE || parser->model == BEACON) pressure = array_uint16_le (data + offset + 4); - else + else if (parser->model == DSX) { + pressure = array_uint16_le (data + offset + 14); + tank = ((data[offset] & 0xF0) >> 4) - 1; + } else { pressure -= data[offset + 1]; + } sample.pressure.tank = tank; sample.pressure.value = pressure * PSI / BAR; if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata); @@ -891,11 +990,17 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ parser->model == I470TC || parser->model == I200CV2 || parser->model == GEOAIR) depth = (data[offset + 4] + (data[offset + 5] << 8)) & 0x0FFF; + else if (parser->model == I330R || parser->model == DSX) + depth = array_uint16_le (data + offset + 2); else if (parser->model == ATOM1) depth = data[offset + 3] * 16; else depth = (data[offset + 2] + (data[offset + 3] << 8)) & 0x0FFF; - sample.depth = depth / 16.0 * FEET; + if (parser->model == I330R || parser->model == DSX) { + sample.depth = depth / 10.0 * FEET; + } else { + sample.depth = depth / 16.0 * FEET; + } if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata); // Gas mix @@ -904,8 +1009,11 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ if (parser->model == TX1) { gasmix = data[offset] & 0x07; have_gasmix = 1; + } else if (parser->model == DSX) { + gasmix = (data[offset] & 0xF0) >> 4; + have_gasmix = 1; } - if (have_gasmix && gasmix != gasmix_previous) { + if (have_gasmix && gasmix != gasmix_previous && parser->ngasmixes > 0) { if (gasmix < 1 || gasmix > parser->ngasmixes) { ERROR (abstract->context, "Invalid gas mix index (%u).", gasmix); return DC_STATUS_DATAFORMAT; @@ -950,11 +1058,25 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ decostop = (data[offset + 7] & 0xF0) >> 4; decotime = array_uint16_le(data + offset + 6) & 0x0FFF; have_deco = 1; + } else if (parser->model == I330R || parser->model == DSX) { + decostop = data[offset + 8]; + if (decostop) { + // Deco time + decotime = array_uint16_le(data + offset + 6); + } else { + // NDL + decotime = array_uint16_le(data + offset + 4); + } + have_deco = 1; } if (have_deco) { if (decostop) { sample.deco.type = DC_DECO_DECOSTOP; - sample.deco.depth = decostop * 10 * FEET; + if (parser->model == I330R || parser->model == DSX) { + sample.deco.depth = decostop * FEET; + } else { + sample.deco.depth = decostop * 10 * FEET; + } } else { sample.deco.type = DC_DECO_NDL; sample.deco.depth = 0.0; @@ -987,6 +1109,13 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ if (callback) callback (DC_SAMPLE_RBT, &sample, userdata); } + // PPO2 + if (parser->model == I330R) { + sample.ppo2.sensor = DC_SENSOR_NONE; + sample.ppo2.value = data[offset + 9] / 100.0; + if (callback) callback (DC_SAMPLE_PPO2, &sample, userdata); + } + // Bookmarks unsigned int have_bookmark = 0; if (parser->model == OC1A || parser->model == OC1B || diff --git a/src/oceanic_common.c b/src/oceanic_common.c index 62f5f74..05d5006 100644 --- a/src/oceanic_common.c +++ b/src/oceanic_common.c @@ -51,6 +51,9 @@ get_profile_first (const unsigned char data[], const oceanic_common_layout_t *la value = array_uint16_le (data + 4); } else if (layout->pt_mode_logbook == 3) { value = array_uint16_le (data + 16); + } else if (layout->pt_mode_logbook == 4) { + first = array_uint32_le (data + 8); + last = array_uint32_le (data + 12); } else { return array_uint16_le (data + 16); } diff --git a/src/oceanic_common.h b/src/oceanic_common.h index 045dca4..94e4c6a 100644 --- a/src/oceanic_common.h +++ b/src/oceanic_common.h @@ -125,8 +125,12 @@ extern "C" { #define I200CV2 0x4749 #define GEOAIR 0x474B +// i330r +#define DSX 0x4741 +#define I330R 0x4744 + #define PAGESIZE 0x10 -#define FPMAXSIZE 0x20 +#define FPMAXSIZE 0x200 #define OCEANIC_COMMON_MATCH(version,patterns,firmware) \ oceanic_common_match ((version), (patterns), \ diff --git a/src/parser.c b/src/parser.c index d63c5c6..ba78399 100644 --- a/src/parser.c +++ b/src/parser.c @@ -127,6 +127,7 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, const unsigned rc = oceanic_veo250_parser_create (&parser, context, data, size, model); break; case DC_FAMILY_OCEANIC_ATOM2: + case DC_FAMILY_PELAGIC_I330R: if (model == REACTPROWHITE) rc = oceanic_veo250_parser_create (&parser, context, data, size, model); else diff --git a/src/pelagic_i330r.c b/src/pelagic_i330r.c new file mode 100644 index 0000000..9e3424c --- /dev/null +++ b/src/pelagic_i330r.c @@ -0,0 +1,2495 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + libdivecomputer/src/pelagic_i330r.c at master · libdivecomputer/libdivecomputer · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ Skip to content + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + + + + + +
+ + + + + + + + + +
+
+
+ + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + / + + libdivecomputer + + + Public +
+ + +
+ +
+ + +
+
+ +
+
+ + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + +

Latest commit

 

History

History
646 lines (539 loc) · 19.8 KB

pelagic_i330r.c

File metadata and controls

646 lines (539 loc) · 19.8 KB
+
+ + + + +
+ +
+ +
+
+ +
+ +
+

Footer

+ + + + +
+
+ + + + + © 2024 GitHub, Inc. + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + diff --git a/src/pelagic_i330r.h b/src/pelagic_i330r.h new file mode 100644 index 0000000..a42102a --- /dev/null +++ b/src/pelagic_i330r.h @@ -0,0 +1,2391 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + libdivecomputer/src/pelagic_i330r.h at master · libdivecomputer/libdivecomputer · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ Skip to content + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + + + + + +
+ + + + + + + + + +
+
+
+ + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + / + + libdivecomputer + + + Public +
+ + +
+ +
+ + +
+
+ +
+
+ + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + +

Latest commit

 

History

History
40 lines (35 loc) · 1.25 KB

pelagic_i330r.h

File metadata and controls

40 lines (35 loc) · 1.25 KB
+
+ + + + +
+ +
+ +
+
+ +
+ +
+

Footer

+ + + + +
+
+ + + + + © 2024 GitHub, Inc. + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + +
+ +
+
+ + +