diff OSTC3Operations.cpp @ 1:0b3630a29ad8

Initial version based on previous repository. Project was ported to QT6 and in now cmake based.
author Ideenmodellierer <tiefenrauscher@web.de>
date Thu, 27 Nov 2025 18:40:28 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OSTC3Operations.cpp	Thu Nov 27 18:40:28 2025 +0100
@@ -0,0 +1,685 @@
+//////////////////////////////////////////////////////////////////////////////
+/// \file   OSTC3Operations.cpp
+/// \brief  Implementing various operations for OSTC3 dive computer
+/// \author JD Gascuel.
+///
+/// \copyright (c) 2011-2016 JD Gascuel. All rights reserved.
+/// $Id$
+//////////////////////////////////////////////////////////////////////////////
+//
+// BSD 2-Clause License:
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+//    this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include "OSTC3Operations.h"
+
+#include "Utils/Exception.h"
+#include "Utils/Log.h"
+#include "Utils/ProgressEvent.h"
+
+#include "SettingsDialog.h"
+#include "HexFile.h"
+
+#include <QApplication>
+#include <QDateTime>
+#include <QDir>
+#include <QRegularExpression>
+
+// Byte extration, compatible littleendian or bigendian.
+#define LOW(x)      ((unsigned char)((x) % 256))
+#define HIGH(x)     ((unsigned char)((x / (1<<8)) % 256))
+#define UPPER(x)    ((unsigned char)((x / (1<<16)) % 256))
+#define UP32(x)     ((unsigned char)((x / (1<<24)) % 256))
+
+#define FIRMWARE_AREA   0x3E0000
+#define FIRMWARE_SIZE   0x01E000        // 120KB
+#define FIRMWARE_BLOCK    0x1000        //   4KB
+
+//////////////////////////////////////////////////////////////////////////////
+
+OSTC3Operations::OSTC3Operations()
+  : descriptionString(""),
+    emulatorName("OSTC3"),
+    _computerFirmware(0),
+    _computerSerial(0),
+    _connectMode(CLOSED_MODE)
+{
+    memset(computerText, 0, sizeof computerText);
+}
+
+OSTC3Operations::~OSTC3Operations()
+{
+    if( _connectMode != CLOSED_MODE )
+        disconnect(true);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+QStringList OSTC3Operations::listPorts() const
+{
+    return listUSBPorts();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+bool OSTC3Operations::connect()
+{
+    LOG_TRACE( "Enter download mode..." );
+
+    try {
+        _connectMode = CLOSED_MODE;
+        _serial.open( Settings::port, emulatorName);
+        _serial.sleep(333);    // Initial 1/3 sec. delay to first comm.
+
+        for(int retry=0; retry < 10; ++retry)
+        {
+            // Allow for 0.1sec extra delay
+            try {
+                _serial.writeByte(0xBB);
+            } catch(const WriteTimeout& ) {
+                // Bluetooth not present: one can open the pseudo COM port,
+                // but we will have a timeout on first write byte...
+                if( retry < 9 ) {
+                    LOG_INFO("Cannot connect to " << Settings::port <<" (" << (retry+1) << "/10)...");
+                    _serial.sleep(1000);
+                    continue;
+                }
+                LOG_THROW("Cannot connect to " << model() <<".");
+                return false;
+            }
+
+            _serial.sleep(100);
+
+            //---- Check acknowledge, w/o fatal timeouts.
+            unsigned char ok   = 0;
+            unsigned char echo = 0;
+            try {
+                echo = _serial.readByte();
+
+                // Already in connect() mode ???
+                if( echo == 'M' )
+                    break;
+
+                ok = _serial.readByte();
+            }
+            catch(const ReadTimeout&) {
+                LOG_INFO("Retry " << (retry+1) << "/10...");
+            }
+
+            if( echo != 0xBB || ok != 0x4D ) {  // DOWNLOAD modes only.
+                if( retry < 9 )
+                {
+                    _serial.purge();
+                    _serial.sleep(400);
+                    continue;
+                }
+                LOG_THROW("Unable to enter hwOS service mode");
+                return false;
+            }
+            break;
+        }
+        getIdentity();
+
+        QString banner = Log::applicationName();
+        writeText(banner);
+        LOG_TRACE("Connected.");
+        _connectMode = DOWNLOAD_MODE;
+        return true;
+    }
+    catch(const Exception& e) {
+        disconnect();
+        LOG_THROW("Port " << Settings::port << ": " << e.what());
+    }
+    return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+bool OSTC3Operations::disconnect(bool /*closing*/)
+{
+    if( _connectMode == CLOSED_MODE ) return false;
+
+    descriptionString.clear();  // cleanup for interface updateStatus()
+    _connectMode = CLOSED_MODE;
+
+    _serial.purge();
+    _serial.writeByte(0xFF);    // Exit communications, just in case...
+    _serial.sleep(100);
+
+    _serial.purge();
+    _serial.close();
+
+    return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void OSTC3Operations::getIdentity()
+{
+    descriptionString.clear();
+
+    LOG_TRACE("Getting model...");
+    HardwareDescriptor hw = hardwareDescriptor();
+ //   if( hw != HW_OSTC3 )
+ //        LOG_THROW("Not an OSTC3.");
+
+    LOG_TRACE("Getting identity...");
+    getCommonIdentity();
+
+    LOG_INFO("Found " << descriptionString.trimmed());
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void OSTC3Operations::getCommonIdentity()
+{
+    unsigned char echo = retryCommand(_serial, 'i'); // 0x69
+    if( echo != 'i' )
+        LOG_THROW("Bad identity reply (1)");
+
+    unsigned char header[4 + 60 + 1] = {0};
+    _serial.readBlock(header, sizeof header);
+    if( header[64] != 0x4D )    // DOWNLOAD modes only.
+        LOG_THROW("Bad identity reply (2)");
+
+    _computerSerial   = header[0] + header[1]*256;
+    _computerFirmware = header[2] * 100 + header[3];
+    memcpy(computerText, header+4, sizeof computerText);
+
+    descriptionString = QString("%1 #%2, fw %3.%4, %5")
+            .arg(model())
+            .arg(serialNumber(), 4, 10, QChar('0'))
+            .arg(firmware() / 100).arg(firmware() % 100, 2, 10, QChar('0'))
+            .arg( QString::fromLatin1((char*)(computerText), 60)
+                .replace(QChar('\0'), " ") );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+int OSTC3Operations::firmware() const
+{
+    return _computerFirmware;
+}
+
+int OSTC3Operations::serialNumber() const
+{
+    return _computerSerial;
+}
+
+QString OSTC3Operations::customText() const
+{
+    return QString::fromLatin1(computerText, sizeof computerText);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+QSize OSTC3Operations::nameSize() const
+{
+    return QSize(12, 5);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void OSTC3Operations::writeText(const QString& msg)
+{
+    QByteArray buffer = msg.leftJustified(16, ' ', true).toLatin1();
+    LOG_TRACE("Echoing string '" << buffer << "'");
+
+    // 2014-10-27 jDG: On OSTC3 v1.60, after an ERASE AREA, we do get
+    //                 a spurious L here (instead of n)...
+    unsigned char echo = retryCommand(_serial, 'n'); // 0x6E Echo string.
+    if( echo != 'n' )
+        LOG_THROW("Bad message reply (1)");
+
+    _serial.writeBlock((const unsigned char*)buffer.data(), 16);
+    _serial.sleep(25);  // Allow 25msec to display the message...
+
+    unsigned char ok = _serial.readByte();
+    if( ok != 0x4C && ok != 0x4D )      // DOWNLOAD or SERVICE modes.
+        LOG_THROW("Bad message reply (2)");
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void OSTC3Operations::setDate(const QDateTime &date)
+{
+    LOG_TRACE("Set Date " << date.toString("MM/dd/yyyy hh:mm"));
+
+    unsigned char buffer[6];
+    buffer[0] = date.time().hour();
+    buffer[1] = date.time().minute();
+    buffer[2] = date.time().second();
+    buffer[3] = date.date().month();
+    buffer[4] = date.date().day();
+    buffer[5] = date.date().year() % 100;
+
+    unsigned char echo = retryCommand(_serial, 'b'); // 0x62 Sync date
+    if( echo != 'b' )
+        LOG_THROW("Bad clock reply (1)");
+
+    _serial.writeBlock(buffer, sizeof buffer);
+    _serial.sleep(5);
+
+    unsigned char ok = _serial.readByte();
+    if( ok != 0x4D )    // DOWNLOAD mode only.
+        LOG_THROW("Bad clock reply (2)");
+
+    writeText( "Set " + date.toString("MM/dd hh:mm") );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void OSTC3Operations::setName(const QString &newName)
+{
+    LOG_TRACE("Set Name '" << newName << "'");
+
+    char buffer[60];
+    memset(buffer, 0, sizeof buffer);
+    strncpy(buffer, newName.toLatin1().constData(), sizeof buffer);
+
+    unsigned char echo = retryCommand(_serial, 'c'); // 0x63 Send custom text
+    if( echo != 'c' )
+        LOG_THROW("Bad text reply (1)");
+
+    _serial.writeBlock((unsigned char*)buffer, sizeof buffer);
+    _serial.sleep(5);
+
+    unsigned char ok = _serial.readByte();
+    if( ok != 0x4D )    // DOWNLOAD modes only.
+        LOG_THROW("Bad text reply (2)");
+
+    getIdentity();
+    // Echo the first line of customtext:
+    writeText(newName.left(12).trimmed());
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void OSTC3Operations::setIcons(const QString &)
+{
+    LOG_THROW("Set icons: Not yet implemented");
+}
+
+QImage OSTC3Operations::dumpScreen() const
+{
+    LOG_THROW("Dump screen: Not yet implemented");
+    return QImage();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+static unsigned char ostc3SecretKey[16] = {
+    241,233, 176, 48,
+     69,111, 190, 85,
+    255,231, 248, 49,
+     19,108, 242,254
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+void OSTC3Operations::eraseRange(unsigned int addr, unsigned int size)
+{
+    // Convert size to number of pages, rounded up.
+    size = ((size + 4095) / 4096);
+
+    // Erase just the needed pages.
+    unsigned char buffer[4];
+    buffer[0] = UPPER(addr);
+    buffer[1] = HIGH(addr);
+    buffer[2] = LOW(addr);
+    buffer[3] = LOW(size);
+
+    unsigned char reply = retryCommand(_serial, 'B');    // Command 'B'
+    if( reply != 0x42 )
+        LOG_THROW("eraseRange (1)");
+
+    _serial.writeBlock(buffer, 4);
+
+    // Wait (120/4)ms by block of 4K, plus 3% VAT to be sure.
+    _serial.sleep(40 + size * 31);
+
+    unsigned char ok = _serial.readByte();
+    if( ok != 0x4c )                    // SERVICE MODE acknowledge.
+        LOG_THROW("eraseRange (2)");
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void OSTC3Operations::writeBlock(unsigned int addr,
+                                 const unsigned char *data,
+                                 unsigned int size)
+{
+    unsigned char buffer[3];
+    buffer[0] = UPPER(addr);
+    buffer[1] = HIGH(addr);
+    buffer[2] = LOW(addr);
+
+    unsigned char reply = retryCommand(_serial, '0');    // 0x30
+    if( reply != '0' )
+        LOG_THROW("startWrite");
+
+    _serial.writeBlock(buffer, sizeof buffer);
+    _serial.sleep(2);
+
+    _serial.writeBlock(data, size);
+    // Approximated EEPROM write time some 1sec timeout ??
+    // 1KB = 240 + 1000 = 1240 : Ok.
+    // 4KB = 1.1sec            : Ok.
+    _serial.sleep(1100);
+
+    unsigned char ok = _serial.readByte();
+    if( ok != 0x4c && ok != 0x4d )      // DOWNLOAD or SERVICE modes.
+        LOG_THROW("stopWrite");
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+void OSTC3Operations::readBlock(unsigned int addr, unsigned char* ptr, unsigned int size)
+{
+    unsigned char buffer[6];
+    buffer[0] = UPPER(addr);
+    buffer[1] = HIGH(addr);
+    buffer[2] = LOW(addr);
+    buffer[3] = UPPER(size);
+    buffer[4] = HIGH(size);
+    buffer[5] = LOW(size);
+
+    unsigned char reply = retryCommand(_serial, 0x20);   // Command ' '
+    if( reply != 0x20 )
+        LOG_THROW("readBytes");
+
+    _serial.writeBlock(buffer, sizeof buffer);
+    _serial.sleep(500);         // Allow some time to start emitting...
+    _serial.readBlock(ptr, size);
+
+    // Note: in that case, the OK byte is send AFTER the data block.
+    unsigned char ok = _serial.readByte();
+    if( ok != 0x4C )                    // SERVICE modes only.
+        LOG_THROW("readBytes (2)");
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void OSTC3Operations::upgradeFirmware(unsigned int checksum)
+{
+    unsigned char buffer[5];
+    buffer[0] = LOW(checksum);
+    buffer[1] = HIGH(checksum);
+    buffer[2] = UPPER(checksum);
+    buffer[3] = UP32(checksum);
+
+    // Compute magic checksum's checksum.
+    buffer[4] = 0x55;
+    buffer[4] ^= buffer[0]; buffer[4] =(buffer[4]<<1 | buffer[4]>>7);
+    buffer[4] ^= buffer[1]; buffer[4] =(buffer[4]<<1 | buffer[4]>>7);
+    buffer[4] ^= buffer[2]; buffer[4] =(buffer[4]<<1 | buffer[4]>>7);
+    buffer[4] ^= buffer[3]; buffer[4] =(buffer[4]<<1 | buffer[4]>>7);
+
+    unsigned char reply = retryCommand(_serial, 0x50);    // 'P' : send FW to bootloader
+    if( reply != 0x50 )
+        LOG_THROW("Flashing start (1)");
+
+    _serial.writeBlock(buffer, sizeof buffer);
+   unsigned char ok = _serial.readByte();
+    if( ok != 0x4C )                    // SERVICE modes only.
+        LOG_THROW("Flashing start (2)");
+
+    // NOTE: the device never return, because it always do a reset,
+    //       with ot without reprogramming...
+    _serial.sleep(500);
+    _serial.close();
+    descriptionString.clear();
+}
+
+QString OSTC3Operations::firmwareTemplate() const
+{
+    return "*_firmware.hex";
+}
+
+#if 0
+QRegExp OSTC3Operations::portTemplate() const
+{
+#if defined(Q_OS_MAC)
+    return QRegExp("tty.usbserial-.*", Qt::CaseInsensitive);
+#elif defined(Q_OS_LINUX)
+    // Seems ok for debian, ubuntu, redhat, CentOS and SUSE (google dixit)
+    return QRegExp("ttyUSB.*", Qt::CaseSensitive);
+#elif defined(Q_OS_WIN)
+    return QRegExp("COM.*", Qt::CaseSensitive);
+#endif
+}
+#endif
+
+QRegularExpression OSTC3Operations::portTemplate() const
+{
+#if defined(Q_OS_MAC)
+    return QRegularExpression("tty.usbserial-.*",
+                              QRegularExpression::CaseInsensitiveOption);
+#elif defined(Q_OS_LINUX)
+    // Debian, Ubuntu, RedHat, CentOS, SUSE
+    return QRegularExpression("ttyUSB.*"); // default: case-sensitive
+#elif defined(Q_OS_WIN)
+    return QRegularExpression("COM.*");    // default: case-sensitive
+#endif
+}
+//////////////////////////////////////////////////////////////////////////////
+
+void OSTC3Operations::connectServiceMode()
+{
+    LOG_TRACE( "Enter service mode..." );
+
+    // NOTE: Service mode requires a special starting sequence, different from
+    //       the usual download mode state.
+    //       Also, the general acknowledge byte is changed to 0x4c 'L'.
+
+    assert( _connectMode != SERVICE_MODE );
+    _serial.open( Settings::port, emulatorName);
+    _serial.sleep(333); // Initial 1/3 sec before trying service mode...
+
+    for(int retry=0; retry < 10; ++retry)
+    {
+        unsigned char serviceMode[] = { 0xAA, 0xAB, 0xCD, 0xEF };
+
+        try {
+            _serial.writeBlock(serviceMode, sizeof serviceMode);
+        }
+        catch(const WriteTimeout&) {
+            // Bluetooth not present: one can open the pseudo COM port,
+            // but we will have a timeout on first write byte...
+            if( retry < 9 ) {
+                LOG_INFO("Cannot connect to " << Settings::port <<" (" << (retry+1) << "/10)...");
+                _serial.sleep(1000);
+                continue;
+            }
+            LOG_THROW("Cannot connect to " << model() << ".");
+            return;
+        }
+
+        // Allow for 0.1sec extra delay
+        _serial.sleep(100);
+
+        //---- Check acknowledge:
+        unsigned char echo = 0;
+        try {
+            echo = _serial.readByte();
+        }
+        catch(...) {}
+
+        if( echo != 0x4b ) {
+serviceModeFailed:
+            if( retry < 9 )
+            {
+                _serial.purge();
+                _serial.sleep(400);
+                continue;
+            }
+            LOG_THROW("Unable to enter " << model() <<" service mode");
+        }
+
+        echo = _serial.readByte();
+        if( echo != 0xAB )
+            goto serviceModeFailed;
+        echo = _serial.readByte();
+        if( echo != 0xCD )
+            goto serviceModeFailed;
+        echo = _serial.readByte();
+        if( echo != 0xEF )
+            goto serviceModeFailed;
+        echo = _serial.readByte();
+        if( echo != 0x4c )              // SERVICE modes only.
+            goto serviceModeFailed;
+        break;
+    }
+    _connectMode = SERVICE_MODE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void OSTC3Operations::upgradeFW(const QString &fileName)
+{
+    //---- Load and check firmware -------------------------------------------
+    LOG_INFO("Loading firmware.");
+    HexFile hex;
+    loadFirmware(hex, fileName);
+
+    //---- Enter Service Mode ------------------------------------------------
+    connectServiceMode();
+
+    //---- Erase old Firmware ------------------------------------------------
+    PROGRESS(0, FIRMWARE_SIZE);
+    LOG_INFO("Erasing Firmware.");
+
+    writeText(" Erasing FW...");
+    eraseRange(FIRMWARE_AREA, FIRMWARE_SIZE);
+
+    //---- Upload Firmware ---------------------------------------------------
+    LOG_INFO("Uploading firmware.");
+    writeText(" Uploading...");
+
+    for(int len = 0x00000; len < FIRMWARE_SIZE; len += FIRMWARE_BLOCK)
+    {
+        unsigned char percent = int(len * 100.0f / FIRMWARE_SIZE + 0.5f);
+        writeText( QString(" Uploading %1%")
+                       .arg(percent, 2) );
+        PROGRESS(percent, 100);
+
+        writeBlock(FIRMWARE_AREA+len, hex.data()+len, FIRMWARE_BLOCK);
+    }
+    PROGRESS(100, 100);
+
+    //---- Verify firmware ---------------------------------------------------
+    LOG_INFO("Verify firmware.");
+    writeText(" Verifying...");
+    {
+        unsigned char* buffer = new unsigned char[FIRMWARE_SIZE];
+        Q_CHECK_PTR(buffer);
+
+        for(int len = 0x00000; len < FIRMWARE_SIZE; len += FIRMWARE_BLOCK)
+        {
+            unsigned char percent = int(len * 100.0f / FIRMWARE_SIZE + 0.5f);
+            writeText( QString(" Verifying %1%")
+                        .arg(percent, 2) );
+            PROGRESS(percent, 100);
+
+            readBlock(FIRMWARE_AREA+len, buffer+len, FIRMWARE_BLOCK);
+        }
+        PROGRESS(100, 100);
+        qApp->processEvents(QEventLoop::ExcludeUserInputEvents, 10);
+
+        for(int i=0; i<FIRMWARE_SIZE; ++i)
+            if( buffer[i] != hex.data()[i] )
+            {
+                writeText(" Verify FAILED");
+                LOG_THROW("readback is different");
+            }
+
+        delete[] buffer;
+    }
+    PROGRESS_THROTTLE();
+
+    //---- Flashing firmware -------------------------------------------------
+    LOG_INFO("Programming.");
+    writeText(" Programming...");
+    upgradeFirmware( hex.checksum() );
+
+    //---- Done --------------------------------------------------------------
+    // Low-level close, to avoid trying to send a 0xFF byte...
+    _serial.close();
+    _connectMode = CLOSED_MODE;
+    LOG_INFO("Upgrade done.");
+    PROGRESS_RESET();
+}
+
+void OSTC3Operations::loadFirmware(HexFile& hex, const QString& fileName) const
+{
+    hex.allocate(FIRMWARE_SIZE);
+    hex.loadEncrypted(fileName, ostc3SecretKey);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+QString OSTC3Operations::model() const
+{
+    return "OSTC hwOS (USB)";
+}
+
+QString OSTC3Operations::description()
+{
+    return descriptionString;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+HardwareOperations::CompanionFeatures OSTC3Operations::supported() const
+{
+    // No ICON, no DUMPSCREEN, no VPM
+    return CompanionFeatures(PARAMETERS|DATE|NAME|FIRMWARE
+                     |HELIUM_DIVE|CCR_DIVE);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void OSTC3Operations::getSignal()
+{
+    return;
+}
+void OSTC3Operations::getAllHeader(unsigned char* pBuffer)
+{
+    return;
+}
+void OSTC3Operations::writeAllHeader(unsigned char* pBuffer)
+{
+    return;
+}
+
+void OSTC3Operations::getAllSamples(unsigned char* pBuffer)
+{
+    return;
+}
+void OSTC3Operations::writeAllSamples(unsigned char* pBuffer)
+{
+    return;
+}