[PATCH 5/7] This adds read/write of Suunto Vyper configs

Anton Lundin glance at acc.umu.se
Sun Oct 12 07:51:28 PDT 2014


This implements the reading and writing of the configuration varables
from the Suunto Vyper family devices.

Everything here is implemented based on the excellent information on:
http://www.sarnau.info/papers:suunto_vyper

Signed-off-by: Anton Lundin <glance at acc.umu.se>
---
 configuredivecomputerthreads.cpp | 167 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 165 insertions(+), 2 deletions(-)

diff --git a/configuredivecomputerthreads.cpp b/configuredivecomputerthreads.cpp
index 7554467..6f0ff9a 100644
--- a/configuredivecomputerthreads.cpp
+++ b/configuredivecomputerthreads.cpp
@@ -44,6 +44,25 @@
 #define OSTC3_PRESSURE_SENSOR_OFFSET	0x35
 #define OSTC3_SAFETY_STOP		0x36
 
+#define SUUNTO_VYPER_MAXDEPTH             0x1e
+#define SUUNTO_VYPER_TOTAL_TIME           0x20
+#define SUUNTO_VYPER_NUMBEROFDIVES        0x22
+#define SUUNTO_VYPER_COMPUTER_TYPE        0x24
+#define SUUNTO_VYPER_FIRMWARE             0x25
+#define SUUNTO_VYPER_SERIALNUMBER         0x26
+#define SUUNTO_VYPER_CUSTOM_TEXT          0x2c
+#define SUUNTO_VYPER_SAMPLING_RATE        0x53
+#define SUUNTO_VYPER_ALTITUDE_SAFETY      0x54
+#define SUUNTO_VYPER_TIMEFORMAT           0x60
+#define SUUNTO_VYPER_UNITS                0x62
+#define SUUNTO_VYPER_MODEL                0x63
+#define SUUNTO_VYPER_LIGHT                0x64
+#define SUUNTO_VYPER_ALARM_DEPTH_TIME     0x65
+#define SUUNTO_VYPER_ALARM_TIME           0x66
+#define SUUNTO_VYPER_ALARM_DEPTH          0x68
+#define SUUNTO_VYPER_CUSTOM_TEXT_LENGHT   30
+
+
 ReadSettingsThread::ReadSettingsThread(QObject *parent, device_data_t *data)
 	: QThread(parent), m_data(data)
 {
@@ -57,8 +76,112 @@ void ReadSettingsThread::run()
 	rc = dc_device_open(&m_data->device, m_data->context, m_data->descriptor, m_data->devname);
 	if (rc == DC_STATUS_SUCCESS) {
 		DeviceDetails *m_deviceDetails = new DeviceDetails(0);
+		switch (dc_device_get_type(m_data->device)) {
+		case DC_FAMILY_SUUNTO_VYPER:
+			supported = true;
+			unsigned char data[SUUNTO_VYPER_CUSTOM_TEXT_LENGHT + 1];
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_MAXDEPTH, data, 2);
+			if (rc == DC_STATUS_SUCCESS) {
+				// in ft * 128.0
+				int depth = feet_to_mm(data[0] << 8 ^ data[1]) / 128;
+				m_deviceDetails->setMaxDepth(depth);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_TOTAL_TIME, data, 2);
+			if (rc == DC_STATUS_SUCCESS) {
+				int total_time = data[0] << 8 ^ data[1];
+				m_deviceDetails->setTotalTime(total_time);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_NUMBEROFDIVES, data, 2);
+			if (rc == DC_STATUS_SUCCESS) {
+				int number_of_dives = data[0] << 8 ^ data[1];
+				m_deviceDetails->setNumberOfDives(number_of_dives);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_COMPUTER_TYPE, data, 1);
+			if (rc == DC_STATUS_SUCCESS) {
+				const char *model;
+				switch(data[0]) {
+				case 0x03:
+					model = "Stinger";
+					break;
+				case 0x04:
+					model = "Mosquito";
+					break;
+				case 0x0A:
+					model = "new Vyper";
+					break;
+				case 0x0C:
+					model = "Vyper or Cobra";
+					break;
+				case 0x0B:
+					model = "Vytec";
+					break;
+				case 0x0D:
+					model = "Gekko";
+					break;
+				default:
+					model = "UNKNOWN";
+				}
+				m_deviceDetails->setModel(model);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_FIRMWARE, data, 1);
+			if (rc == DC_STATUS_SUCCESS) {
+				m_deviceDetails->setFirmwareVersion(QString::number(data[0]) + ".0.0");
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_SERIALNUMBER, data, 4);
+			if (rc == DC_STATUS_SUCCESS) {
+				int serial_number = data[0] * 1000000 + data[1] * 10000 + data[2] * 100 + data[3];
+				m_deviceDetails->setSerialNo(QString::number(serial_number));
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_CUSTOM_TEXT, data, SUUNTO_VYPER_CUSTOM_TEXT_LENGHT);
+			if (rc == DC_STATUS_SUCCESS) {
+				data[SUUNTO_VYPER_CUSTOM_TEXT_LENGHT] = 0;
+				m_deviceDetails->setCustomText((const char*) data);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_SAMPLING_RATE, data, 1);
+			if (rc == DC_STATUS_SUCCESS) {
+				m_deviceDetails->setSamplingRate((int) data[0]);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_ALTITUDE_SAFETY, data, 1);
+			if (rc == DC_STATUS_SUCCESS) {
+				m_deviceDetails->setAltitude(data[0] & 0x03);
+				m_deviceDetails->setPersonalSafety(data[0] >> 2 & 0x03);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_TIMEFORMAT, data, 1);
+			if (rc == DC_STATUS_SUCCESS) {
+				m_deviceDetails->setTimeFormat(data[0] & 0x01);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_UNITS, data, 1);
+			if (rc == DC_STATUS_SUCCESS) {
+				m_deviceDetails->setUnits(data[0] & 0x01);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_MODEL, data, 1);
+			if (rc == DC_STATUS_SUCCESS) {
+				m_deviceDetails->setDiveMode(data[0] & 0x03);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_LIGHT, data, 1);
+			if (rc == DC_STATUS_SUCCESS) {
+				m_deviceDetails->setLightEnabled(data[0] >> 7);
+				m_deviceDetails->setLight(data[0] & 0x7F);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_ALARM_DEPTH_TIME, data, 1);
+			if (rc == DC_STATUS_SUCCESS) {
+				m_deviceDetails->setAlarmTimeEnabled(data[0] & 0x01);
+				m_deviceDetails->setAlarmDepthEnabled(data[0] >> 1 & 0x01);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_ALARM_TIME, data, 2);
+			if (rc == DC_STATUS_SUCCESS) {
+				m_deviceDetails->setAlarmTime(data[0] << 8 ^ data[1]);
+			}
+			rc = dc_device_read(m_data->device, SUUNTO_VYPER_ALARM_DEPTH, data, 2);
+			if (rc == DC_STATUS_SUCCESS) {
+				int depth = feet_to_mm(data[0] << 8 ^ data[1]) / 128;
+				m_deviceDetails->setAlarmDepth(depth);
+			}
+			emit devicedetails(m_deviceDetails);
+            break;
 #if DC_VERSION_CHECK(0, 5, 0)
-		if (dc_device_get_type(m_data->device) == DC_FAMILY_HW_OSTC3) {
+		case DC_FAMILY_HW_OSTC3:
+		{
 			supported = true;
 			m_deviceDetails->setBrightness(0);
 			m_deviceDetails->setCustomText("");
@@ -300,7 +423,12 @@ void ReadSettingsThread::run()
 
 			emit devicedetails(m_deviceDetails);
 		}
+		break;
 #endif	// divecomputer 0.5.0
+		default:
+			supported = false;
+			break;
+		}
 		dc_device_close(m_data->device);
 
 		if (!supported) {
@@ -330,8 +458,39 @@ void WriteSettingsThread::run()
 	dc_status_t rc;
 	rc = dc_device_open(&m_data->device, m_data->context, m_data->descriptor, m_data->devname);
 	if (rc == DC_STATUS_SUCCESS) {
+		switch (dc_device_get_type(m_data->device)) {
+		case DC_FAMILY_SUUNTO_VYPER:
+			supported = true;
+			unsigned char data;
+			unsigned char data2[2];
+			dc_device_write(m_data->device, SUUNTO_VYPER_CUSTOM_TEXT,
+					// Convert the customText to a 30 char wide padded with " "
+					(const unsigned char *) QString("%1").arg(m_deviceDetails->customText(), -30, QChar(' ')).toUtf8().data(),
+					SUUNTO_VYPER_CUSTOM_TEXT_LENGHT);
+			data = m_deviceDetails->samplingRate();
+			dc_device_write(m_data->device, SUUNTO_VYPER_SAMPLING_RATE, &data, 1);
+			data = m_deviceDetails->personalSafety() << 2 ^ m_deviceDetails->altitude();
+			dc_device_write(m_data->device, SUUNTO_VYPER_ALTITUDE_SAFETY, &data, 1);
+			data = m_deviceDetails->timeFormat();
+			dc_device_write(m_data->device, SUUNTO_VYPER_TIMEFORMAT, &data, 1);
+			data = m_deviceDetails->units();
+			dc_device_write(m_data->device, SUUNTO_VYPER_UNITS, &data, 1);
+			data = m_deviceDetails->diveMode();
+			dc_device_write(m_data->device, SUUNTO_VYPER_MODEL, &data, 1);
+			data = m_deviceDetails->lightEnabled() << 7 ^ (m_deviceDetails->light() & 0x7F);
+			dc_device_write(m_data->device, SUUNTO_VYPER_LIGHT, &data, 1);
+			data = m_deviceDetails->alarmDepthEnabled() << 1 ^ m_deviceDetails->alarmTimeEnabled();
+			dc_device_write(m_data->device, SUUNTO_VYPER_ALARM_DEPTH_TIME, &data, 1);
+			data2[0] = m_deviceDetails->alarmTime() >> 8;
+			data2[1] = m_deviceDetails->alarmTime() & 0xFF;
+			dc_device_write(m_data->device, SUUNTO_VYPER_ALARM_TIME, data2, 2);
+			data2[0] = (int)(mm_to_feet(m_deviceDetails->alarmDepth()) * 128) >> 8;
+			data2[1] = (int)(mm_to_feet(m_deviceDetails->alarmDepth()) * 128) & 0x0FF;
+			dc_device_write(m_data->device, SUUNTO_VYPER_ALARM_DEPTH, data2, 2);
+			break;
 #if DC_VERSION_CHECK(0,5,0)
-		if (dc_device_get_type(m_data->device) == DC_FAMILY_HW_OSTC3) {
+		case DC_FAMILY_HW_OSTC3:
+		{
 			supported = true;
 			//write gas values
 			unsigned char gas1Data[4] = {m_deviceDetails->gas1().oxygen,
@@ -496,6 +655,10 @@ void WriteSettingsThread::run()
 			}
 		}
 #endif	// divecomputer 0.5.0
+		default:
+			supported = false;
+			break;
+		}
 		dc_device_close(m_data->device);
 
 		if (!supported) {
-- 
1.9.1



More information about the subsurface mailing list