diff --git a/companion/src/helpers.cpp b/companion/src/helpers.cpp index f8c3ff65a..78af4d521 100644 --- a/companion/src/helpers.cpp +++ b/companion/src/helpers.cpp @@ -824,22 +824,23 @@ void startSimulation(QWidget * parent, RadioData & radioData, int modelIdx) } SimulatorMainWindow * dialog = new SimulatorMainWindow(parent, simulator, flags); - if (IS_HORUS(getCurrentBoard()) && !dialog->useTempDataPath(true)) { - QMessageBox::critical(NULL, QObject::tr("Data Load Error"), QObject::tr("Error: Could not create temporary directory in '%1'").arg(QDir::tempPath())); + if (!dialog->setRadioData(simuData)) { + QMessageBox::critical(NULL, QObject::tr("Data Load Error"), QObject::tr("Error occurred while starting simulator.")); delete dialog; delete simuData; return; } - dialog->setRadioData(simuData); + dialog->setWindowModality(Qt::ApplicationModal); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->start(); - dialog->show(); QObject::connect(dialog, &SimulatorMainWindow::destroyed, [simuData] (void) { // TODO simuData and Horus tmp directory is deleted on simulator close OR we could use it to get back data from the simulation delete simuData; }); + + dialog->show(); } else { QMessageBox::warning(NULL, diff --git a/companion/src/simulation/simulatordialog.cpp b/companion/src/simulation/simulatordialog.cpp index 716f75c77..473e6fd9c 100644 --- a/companion/src/simulation/simulatordialog.cpp +++ b/companion/src/simulation/simulatordialog.cpp @@ -172,10 +172,10 @@ void SimulatorDialog::setRadioSettings(const GeneralSettings settings) /* * This function can accept no parameters, a file name (QString is a QBA), or a data array. It will attempt to load radio settings data from one of * several sources into a RadioData object, parse the data, and then pass it on as appropriate to the SimulatorInterface in start(). - * If given no/blank , and setDataPath() was already called, then it will check that directory for "Horus-style" data files. + * If given no/blank , and setDataPath() was already called, then it will check that directory for "Horus-style" data files. * If given a file name, set the parameter to 'true'. This will attempt to load radio settings from said file * and later start the simulator interface in start() using the same data. - * If is a byte array of data, attempts to load radio settings from there and will also start the simulator interface + * If is a byte array of data, attempts to load radio settings from there and will also start the simulator interface * with the same data when start() is called. * If you already have a valid RadioData structure, call setRadioData() instead. */ @@ -185,7 +185,7 @@ bool SimulatorDialog::setStartupData(const QByteArray & dataSource, bool fromFil quint16 ret = 1; QString error; - // If is blank but we have a data path, use that for individual radio/model files. + // If is blank but we have a data path, use that for individual radio/model files. if (dataSource.isEmpty() && !radioDataPath.isEmpty()) { // If directory structure already exists, try to load data from there. // FIXME : need Storage class to return formal error code, not just a boolean, because it would be better @@ -197,33 +197,25 @@ bool SimulatorDialog::setStartupData(const QByteArray & dataSource, bool fromFil } } // Supposedly we're being given a file name to use, try that out. - else if (fromFile) { + else if (fromFile && !dataSource.isEmpty()) { Storage store = Storage(QString(dataSource)); - if ((ret = store.load(simuData))) { - if (IS_HORUS(m_board)) { - // save the data to a temp folder - if (!(ret = useTempDataPath(true, true))) // save data back to file on simulator close - error = tr("Error: Could not save data to temporary directory in '%1'").arg(QDir::tempPath()); - else - ret = saveRadioData(&simuData, radioDataPath, &error); - } - else if (QString(dataSource).endsWith(".otx", Qt::CaseInsensitive)) { - // FIXME : Right now there's no way to read data back into the .otx file after simulation finishes. - return setRadioData(&simuData); - } - else { - startupData = dataSource; // save the file name for start() - } - } - // again there's no way to tell what the error from Storage actually was, so if the file doesn't exist we'll create a new one - else if (!dataSource.isEmpty() && !QFile(QString(dataSource)).exists()) { - startupData = dataSource; - startupFromFile = true; - return true; + ret = store.load(simuData); + if (!ret && QFile(QString(dataSource)).exists()) { + error = store.error(); } else { - ret = 0; - error = store.error(); + if (QString(dataSource).endsWith(".otx", Qt::CaseInsensitive)) { + // no radios can work with .otx files directly, so we load contents into either + // a temporary folder (Horus) or local data array (other radios) which we'll save back to .otx upon exit + if ((ret = setRadioData(&simuData))) { + startupFromFile = false; + return true; + } + } + else { + // the binary file will be read/written directly by the fw interface, save the file name for simulator->start() + startupData = dataSource; + } } } // Assume a byte array of radio data was passed, load it. @@ -252,16 +244,27 @@ bool SimulatorDialog::setStartupData(const QByteArray & dataSource, bool fromFil bool SimulatorDialog::setRadioData(RadioData * radioData) { - bool ret = false; - if (radioDataPath.isEmpty()) { - QByteArray eeprom(getEEpromSize(m_board), 0); - if (firmware->getEEpromInterface()->save((uint8_t *)eeprom.data(), *radioData, 0, firmware->getCapability(SimulatorVariant)) > 0) - ret = setStartupData(eeprom, false); - } - else { - if ((ret = saveRadioData(radioData, radioDataPath))) - radioSettings = radioData->generalSettings; + bool ret = true; + + saveTempRadioData = (flags & SIMULATOR_FLAGS_STANDALONE); + + if (IS_HORUS(m_board)) + ret = useTempDataPath(true); + + if (ret) { + if (radioDataPath.isEmpty()) { + startupData.fill(0, getEEpromSize(m_board)); + if (firmware->getEEpromInterface()->save((uint8_t *)startupData.data(), *radioData, 0, firmware->getCapability(SimulatorVariant)) <= 0) + ret = false; + } + else { + ret = saveRadioData(radioData, radioDataPath); + } } + + if (ret) + radioSettings = radioData->generalSettings; + return ret; } @@ -306,7 +309,7 @@ bool SimulatorDialog::saveRadioData(RadioData * radioData, const QString & path, return false; } -bool SimulatorDialog::useTempDataPath(bool deleteOnClose, bool saveOnClose) +bool SimulatorDialog::useTempDataPath(bool deleteOnClose) { if (deleteTempRadioData) deleteTempData(); @@ -316,9 +319,7 @@ bool SimulatorDialog::useTempDataPath(bool deleteOnClose, bool saveOnClose) setDataPath(tmpDir.path()); tmpDir.setAutoRemove(false); deleteTempRadioData = deleteOnClose; - saveTempRadioData = saveOnClose; - qDebug() << __FILE__ << __LINE__ << "Created temporary settings directory" << radioDataPath - << "with delteOnClose:" << deleteOnClose << "with saveOnClose:" << saveOnClose; + qDebug() << __FILE__ << __LINE__ << "Created temporary settings directory" << radioDataPath << "with delteOnClose:" << deleteOnClose; return true; } else { @@ -334,24 +335,47 @@ bool SimulatorDialog::saveTempData() QString error; QString file = g.profile[radioProfileId].simulatorOptions().dataFile; - if (radioDataPath.isEmpty() || file.isEmpty()) - return ret; + if (!file.isEmpty()) { + RadioData radioData; - RadioData radioData; - SdcardFormat sdcard(radioDataPath); - if (!(ret = sdcard.load(radioData))) { - error = sdcard.error(); - } - else { - Storage store(file); - if (!(ret = store.write(radioData))) - error = store.error(); - else - qDebug() << __FILE__ << __LINE__ << "Saved radio data to file" << file; + if (radioDataPath.isEmpty()) { + if (!startupData.isEmpty()) { + if (!QFile(file).exists()) { + QFile fh(file); + if (!fh.open(QIODevice::WriteOnly)) + error = tr("Error saving data: could open file for writing: '%1'").arg(file); + else + fh.close(); + } + + if (!firmware->getEEpromInterface()->load(radioData, (uint8_t *)startupData.constData(), getEEpromSize(m_board))) { + error = tr("Error saving data: could not get data from simulator interface."); + } + else { + radioData.fixModelFilenames(); + ret = true; + } + } + } + else { + SdcardFormat sdcard(radioDataPath); + if (!(ret = sdcard.load(radioData))) + error = sdcard.error(); + } + if (ret) { + Storage store(file); + if (!(ret = store.write(radioData))) + error = store.error(); + else + qDebug() << __FILE__ << __LINE__ << "Saved radio data to file" << file; + } } - if (!ret) + if (!ret) { + if (error.isEmpty()) + error = tr("An unexpected error occurred while attempting to save radio data to file '%1'.").arg(file); QMessageBox::critical(this, tr("Data Save Error"), error); + } return ret; } @@ -411,6 +435,10 @@ void SimulatorDialog::stop() { timer->stop(); simulator->stop(); + if (saveTempRadioData) { + startupData.fill(0, getEEpromSize(m_board)); + simulator->readEepromData(startupData); + } } void SimulatorDialog::restart() diff --git a/companion/src/simulation/simulatordialog.h b/companion/src/simulation/simulatordialog.h index e2dc55cef..75f2be1f9 100644 --- a/companion/src/simulation/simulatordialog.h +++ b/companion/src/simulation/simulatordialog.h @@ -73,7 +73,7 @@ class SimulatorDialog : public QWidget bool setRadioData(RadioData * radioData); bool setOptions(SimulatorOptions & options, bool withSave = true); bool saveRadioData(RadioData * radioData, const QString & path = "", QString * error = NULL); - bool useTempDataPath(bool deleteOnClose = true, bool saveOnClose = false); + bool useTempDataPath(bool deleteOnClose = true); bool saveTempData(); void deleteTempData(); void saveState(); diff --git a/companion/src/simulation/simulatorinterface.h b/companion/src/simulation/simulatorinterface.h index d9c35d832..42fef7557 100644 --- a/companion/src/simulation/simulatorinterface.h +++ b/companion/src/simulation/simulatorinterface.h @@ -62,7 +62,7 @@ class SimulatorInterface virtual ~SimulatorInterface() {} - virtual void setSdPath(const QString & sdPath = "", const QString & settingsPath = "") { }; + virtual void setSdPath(const QString & sdPath = "", const QString & settingsPath = "") { } virtual void setVolumeGain(int value) { } @@ -72,6 +72,8 @@ class SimulatorInterface virtual void stop() = 0; + virtual void readEepromData(QByteArray & dest) = 0; + virtual bool timer10ms() = 0; virtual uint8_t * getLcd() = 0; diff --git a/companion/src/simulation/simulatormainwindow.cpp b/companion/src/simulation/simulatormainwindow.cpp index 647fc6f31..acaab27aa 100644 --- a/companion/src/simulation/simulatormainwindow.cpp +++ b/companion/src/simulation/simulatormainwindow.cpp @@ -217,9 +217,9 @@ bool SimulatorMainWindow::setRadioData(RadioData * radioData) return m_simulatorWidget->setRadioData(radioData); } -bool SimulatorMainWindow::useTempDataPath(bool deleteOnClose, bool saveOnClose) +bool SimulatorMainWindow::useTempDataPath(bool deleteOnClose) { - return m_simulatorWidget->useTempDataPath(deleteOnClose, saveOnClose); + return m_simulatorWidget->useTempDataPath(deleteOnClose); } bool SimulatorMainWindow::setOptions(SimulatorOptions & options, bool withSave) diff --git a/companion/src/simulation/simulatormainwindow.h b/companion/src/simulation/simulatormainwindow.h index 2250446ef..c69e74512 100644 --- a/companion/src/simulation/simulatormainwindow.h +++ b/companion/src/simulation/simulatormainwindow.h @@ -52,7 +52,7 @@ class SimulatorMainWindow : public QMainWindow ~SimulatorMainWindow(); bool setRadioData(RadioData * radioData); - bool useTempDataPath(bool deleteOnClose = true, bool saveOnClose = false); + bool useTempDataPath(bool deleteOnClose = true); bool setOptions(SimulatorOptions & options, bool withSave = true); QMenu * createPopupMenu(); diff --git a/radio/src/targets/simu/opentxsimulator.cpp b/radio/src/targets/simu/opentxsimulator.cpp index 3256d24bb..46a6a4a5a 100644 --- a/radio/src/targets/simu/opentxsimulator.cpp +++ b/radio/src/targets/simu/opentxsimulator.cpp @@ -116,6 +116,13 @@ void OpenTxSimulator::stop() StopEepromThread(); } +void OpenTxSimulator::readEepromData(QByteArray & dest) +{ +#if defined(EEPROM_SIZE) + memcpy(dest.data(), eeprom, std::min(EEPROM_SIZE, dest.size())); +#endif +} + void OpenTxSimulator::getValues(TxOutputs &outputs) { #define GETVALUES_IMPORT diff --git a/radio/src/targets/simu/opentxsimulator.h b/radio/src/targets/simu/opentxsimulator.h index ab2ffbe31..700a56ef3 100644 --- a/radio/src/targets/simu/opentxsimulator.h +++ b/radio/src/targets/simu/opentxsimulator.h @@ -46,6 +46,8 @@ class DLLEXPORT OpenTxSimulator : public SimulatorInterface { virtual void stop(); + virtual void readEepromData(QByteArray & dest); + virtual bool timer10ms(); virtual uint8_t * getLcd();