/*Copyright © 2017 Hasan Yavuz ÖzderyaThis file is part of serialplot.serialplot is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.serialplot is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with serialplot. If not, see <http://www.gnu.org/licenses/>.*/#include <QtDebug>#include <QtEndian>#include "floatswap.h"#include "framedreader.h"FramedReader::FramedReader(QIODevice* device, ChannelManager* channelMan,DataRecorder* recorder, QObject* parent) :AbstractReader(device, channelMan, recorder, parent){paused = false;// initial settingssettingsInvalid = 0;_numOfChannels = _settingsWidget.numOfChannels();hasSizeByte = _settingsWidget.frameSize() == 0;frameSize = _settingsWidget.frameSize();syncWord = _settingsWidget.syncWord();checksumEnabled = _settingsWidget.isChecksumEnabled();onNumberFormatChanged(_settingsWidget.numberFormat());debugModeEnabled = _settingsWidget.isDebugModeEnabled();checkSettings();// init setting connectionsconnect(&_settingsWidget, &FramedReaderSettings::numberFormatChanged,this, &FramedReader::onNumberFormatChanged);connect(&_settingsWidget, &FramedReaderSettings::numOfChannelsChanged,this, &FramedReader::onNumOfChannelsChanged);connect(&_settingsWidget, &FramedReaderSettings::syncWordChanged,this, &FramedReader::onSyncWordChanged);connect(&_settingsWidget, &FramedReaderSettings::frameSizeChanged,this, &FramedReader::onFrameSizeChanged);connect(&_settingsWidget, &FramedReaderSettings::checksumChanged,[this](bool enabled){checksumEnabled = enabled; reset();});connect(&_settingsWidget, &FramedReaderSettings::debugModeChanged,[this](bool enabled){debugModeEnabled = enabled;});// init reader statereset();}void FramedReader::enable(bool enabled){if (enabled){connect(_device, &QIODevice::readyRead,this, &FramedReader::onDataReady);}else{QObject::disconnect(_device, 0, this, 0);}}QWidget* FramedReader::settingsWidget(){return &_settingsWidget;}unsigned FramedReader::numOfChannels(){return _numOfChannels;}void FramedReader::pause(bool enabled){paused = enabled;}void FramedReader::onNumberFormatChanged(NumberFormat numberFormat){switch(numberFormat){case NumberFormat_uint8:sampleSize = 1;readSample = &FramedReader::readSampleAs<quint8>;break;case NumberFormat_int8:sampleSize = 1;readSample = &FramedReader::readSampleAs<qint8>;break;case NumberFormat_uint16:sampleSize = 2;readSample = &FramedReader::readSampleAs<quint16>;break;case NumberFormat_int16:sampleSize = 2;readSample = &FramedReader::readSampleAs<qint16>;break;case NumberFormat_uint32:sampleSize = 4;readSample = &FramedReader::readSampleAs<quint32>;break;case NumberFormat_int32:sampleSize = 4;readSample = &FramedReader::readSampleAs<qint32>;break;case NumberFormat_float:sampleSize = 4;readSample = &FramedReader::readSampleAs<float>;break;case NumberFormat_INVALID:Q_ASSERT(1); // neverbreak;}checkSettings();reset();}void FramedReader::checkSettings(){// sync word is invalid (empty or missing a nibble at the end)if (!syncWord.size()){settingsInvalid |= SYNCWORD_INVALID;}else // sync word is valid{settingsInvalid &= ~SYNCWORD_INVALID;}// check if fixed frame size is multiple of a sample set sizeif (!hasSizeByte && frameSize % (_numOfChannels * sampleSize) != 0){settingsInvalid |= FRAMESIZE_INVALID;}else{settingsInvalid &= ~FRAMESIZE_INVALID;}// show an error messageif (settingsInvalid & SYNCWORD_INVALID){_settingsWidget.showMessage("Sync word is invalid!", true);}else if (settingsInvalid & FRAMESIZE_INVALID){QString errorMessage =QString("Frame size must be multiple of %1 (#channels * sample size)!")\.arg(_numOfChannels * sampleSize);_settingsWidget.showMessage(errorMessage, true);}else{_settingsWidget.showMessage("All is well!");}}void FramedReader::onNumOfChannelsChanged(unsigned value){_numOfChannels = value;checkSettings();reset();emit numOfChannelsChanged(value);}void FramedReader::onSyncWordChanged(QByteArray word){syncWord = word;checkSettings();reset();}void FramedReader::onFrameSizeChanged(unsigned value){if (value == 0){hasSizeByte = true;}else{hasSizeByte = false;frameSize = value;}checkSettings();reset();}void FramedReader::onDataReady(){if (settingsInvalid) return;// loop until we run out of bytes or more bytes is requiredunsigned bytesAvailable;while ((bytesAvailable = _device->bytesAvailable())){if (!gotSync) // read sync word{char c;_device->getChar(&c);if (c == syncWord[sync_i]) // correct sync byte?{sync_i++;if (sync_i == (unsigned) syncWord.length()){gotSync = true;}}else{if (debugModeEnabled) qCritical() << "Missed " << sync_i+1 << "th sync byte.";}}else if (hasSizeByte && !gotSize) // skipped if fixed frame size{frameSize = 0;_device->getChar((char*) &frameSize);if (frameSize == 0) // check size{qCritical() << "Frame size is 0!";reset();}else if (frameSize % (_numOfChannels * sampleSize) != 0){qCritical() <<QString("Frame size is not multiple of %1 (#channels * sample size)!") \.arg(_numOfChannels * sampleSize);reset();}else{if (debugModeEnabled) qDebug() << "Frame size:" << frameSize;gotSize = true;}}else // read data bytes{// have enough data bytes? (+1 for checksum)if (bytesAvailable < (checksumEnabled ? frameSize+1 : frameSize)){break;}else // read data bytes and checksum{readFrameDataAndCheck();reset();}}}}void FramedReader::reset(){sync_i = 0;gotSync = false;gotSize = false;if (hasSizeByte) frameSize = 0;calcChecksum = 0;}// Important: this function assumes device has enough bytes to read a full frames data and checksumvoid FramedReader::readFrameDataAndCheck(){// if paused just read and waste dataif (paused){_device->read((checksumEnabled ? frameSize+1 : frameSize));return;}// a package is 1 set of samples for all channelsunsigned numOfPackagesToRead = frameSize / (_numOfChannels * sampleSize);double* channelSamples = new double[numOfPackagesToRead * _numOfChannels];for (unsigned i = 0; i < numOfPackagesToRead; i++){for (unsigned int ci = 0; ci < _numOfChannels; ci++){channelSamples[ci*numOfPackagesToRead+i] = (this->*readSample)();}}// read checksumunsigned rChecksum = 0;bool checksumPassed = false;if (checksumEnabled){_device->read((char*) &rChecksum, 1);calcChecksum &= 0xFF;checksumPassed = (calcChecksum == rChecksum);}if (!checksumEnabled || checksumPassed){// commit dataaddData(channelSamples, numOfPackagesToRead*_numOfChannels);}else{qCritical() << "Checksum failed! Received:" << rChecksum << "Calculated:" << calcChecksum;}delete[] channelSamples;}template<typename T> double FramedReader::readSampleAs(){T data;_device->read((char*) &data, sizeof(data));if (checksumEnabled){for (unsigned i = 0; i < sizeof(data); i++){calcChecksum += ((unsigned char*) &data)[i];}}if (_settingsWidget.endianness() == LittleEndian){data = qFromLittleEndian(data);}else{data = qFromBigEndian(data);}return double(data);}void FramedReader::saveSettings(QSettings* settings){_settingsWidget.saveSettings(settings);}void FramedReader::loadSettings(QSettings* settings){_settingsWidget.loadSettings(settings);}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。