kopia lustrzana https://gitlab.com/Teuniz/DSRemote
1096 wiersze
21 KiB
C++
1096 wiersze
21 KiB
C++
/*
|
|
***************************************************************************
|
|
*
|
|
* Author: Teunis van Beelen
|
|
*
|
|
* Copyright (C) 2015, 2016, 2017 Teunis van Beelen
|
|
*
|
|
* Email: teuniz@gmail.com
|
|
*
|
|
***************************************************************************
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
***************************************************************************
|
|
*/
|
|
|
|
|
|
#define SAV_MEM_BSZ (250000)
|
|
|
|
|
|
|
|
void UI_Mainwindow::save_screenshot()
|
|
{
|
|
int n;
|
|
|
|
char str[128],
|
|
opath[MAX_PATHLEN];
|
|
|
|
QPainter painter;
|
|
#if QT_VERSION >= 0x050000
|
|
painter.setRenderHint(QPainter::Qt4CompatiblePainting, true);
|
|
#endif
|
|
|
|
QPainterPath path;
|
|
|
|
if(device == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
scrn_timer->stop();
|
|
|
|
scrn_thread->wait();
|
|
|
|
tmc_write(":DISP:DATA?");
|
|
|
|
save_data_thread get_data_thrd(0);
|
|
|
|
QMessageBox w_msg_box;
|
|
w_msg_box.setIcon(QMessageBox::NoIcon);
|
|
w_msg_box.setText("Downloading data...");
|
|
w_msg_box.setStandardButtons(QMessageBox::Abort);
|
|
|
|
connect(&get_data_thrd, SIGNAL(finished()), &w_msg_box, SLOT(accept()));
|
|
|
|
get_data_thrd.start();
|
|
|
|
if(w_msg_box.exec() != QDialog::Accepted)
|
|
{
|
|
disconnect(&get_data_thrd, 0, 0, 0);
|
|
strcpy(str, "Aborted by user.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
disconnect(&get_data_thrd, 0, 0, 0);
|
|
|
|
n = get_data_thrd.get_num_bytes_rcvd();
|
|
if(n < 0)
|
|
{
|
|
strcpy(str, "Can not read from device.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
if(device->sz != SCRN_SHOT_BMP_SZ)
|
|
{
|
|
strcpy(str, "Error, bitmap has wrong filesize\n");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
if(strncmp(device->buf, "BM", 2))
|
|
{
|
|
strcpy(str, "Error, file is not a bitmap\n");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
memcpy(devparms.screenshot_buf, device->buf, SCRN_SHOT_BMP_SZ);
|
|
|
|
screenXpm.loadFromData((uchar *)(devparms.screenshot_buf), SCRN_SHOT_BMP_SZ);
|
|
|
|
if(devparms.modelserie == 1)
|
|
{
|
|
painter.begin(&screenXpm);
|
|
|
|
painter.fillRect(0, 0, 80, 29, Qt::black);
|
|
|
|
painter.setPen(Qt::white);
|
|
|
|
painter.drawText(5, 8, 65, 20, Qt::AlignCenter, devparms.modelname);
|
|
|
|
painter.end();
|
|
}
|
|
else if(devparms.modelserie == 6)
|
|
{
|
|
painter.begin(&screenXpm);
|
|
|
|
painter.fillRect(0, 0, 95, 29, QColor(48, 48, 48));
|
|
|
|
path.addRoundedRect(5, 5, 85, 20, 3, 3);
|
|
|
|
painter.fillPath(path, Qt::black);
|
|
|
|
painter.setPen(Qt::white);
|
|
|
|
painter.drawText(5, 5, 85, 20, Qt::AlignCenter, devparms.modelname);
|
|
|
|
painter.end();
|
|
}
|
|
|
|
if(devparms.screenshot_inv)
|
|
{
|
|
screenXpm.invertPixels(QImage::InvertRgb);
|
|
}
|
|
|
|
opath[0] = 0;
|
|
if(recent_savedir[0]!=0)
|
|
{
|
|
strcpy(opath, recent_savedir);
|
|
strcat(opath, "/");
|
|
}
|
|
strcat(opath, "screenshot.png");
|
|
|
|
strcpy(opath, QFileDialog::getSaveFileName(this, "Save file", opath, "PNG files (*.png *.PNG)").toLocal8Bit().data());
|
|
|
|
if(!strcmp(opath, ""))
|
|
{
|
|
scrn_timer->start(devparms.screentimerival);
|
|
|
|
return;
|
|
}
|
|
|
|
get_directory_from_path(recent_savedir, opath, MAX_PATHLEN);
|
|
|
|
if(screenXpm.save(QString::fromLocal8Bit(opath), "PNG", 50) == false)
|
|
{
|
|
strcpy(str, "Could not save file (unknown error)");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
scrn_timer->start(devparms.screentimerival);
|
|
|
|
return;
|
|
|
|
OUT_ERROR:
|
|
|
|
if(get_data_thrd.isFinished() != true)
|
|
{
|
|
connect(&get_data_thrd, SIGNAL(finished()), &w_msg_box, SLOT(accept()));
|
|
w_msg_box.setText("Waiting for thread to finish, please wait...");
|
|
w_msg_box.exec();
|
|
}
|
|
|
|
scrn_timer->start(devparms.screentimerival);
|
|
|
|
QMessageBox msgBox;
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
msgBox.setText(str);
|
|
msgBox.exec();
|
|
}
|
|
|
|
|
|
void UI_Mainwindow::get_deep_memory_waveform(void)
|
|
{
|
|
int i, k,
|
|
n=0,
|
|
chn,
|
|
chns=0,
|
|
bytes_rcvd=0,
|
|
mempnts,
|
|
yref[MAX_CHNS],
|
|
empty_buf;
|
|
|
|
char str[256];
|
|
|
|
short *wavbuf[MAX_CHNS];
|
|
|
|
QEventLoop ev_loop;
|
|
|
|
QMessageBox wi_msg_box;
|
|
|
|
save_data_thread get_data_thrd(0);
|
|
|
|
if(device == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
scrn_timer->stop();
|
|
|
|
scrn_thread->wait();
|
|
|
|
for(i=0; i<MAX_CHNS; i++)
|
|
{
|
|
wavbuf[i] = NULL;
|
|
}
|
|
|
|
mempnts = devparms.acquirememdepth;
|
|
|
|
QProgressDialog progress("Downloading data...", "Abort", 0, mempnts, this);
|
|
progress.setWindowModality(Qt::WindowModal);
|
|
progress.setMinimumDuration(0);
|
|
|
|
connect(&get_data_thrd, SIGNAL(finished()), &ev_loop, SLOT(quit()));
|
|
|
|
statusLabel->setText("Downloading data...");
|
|
|
|
for(i=0; i<MAX_CHNS; i++)
|
|
{
|
|
if(!devparms.chandisplay[i])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
chns++;
|
|
}
|
|
|
|
if(!chns)
|
|
{
|
|
strcpy(str, "No active channels.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
if(mempnts < 1)
|
|
{
|
|
strcpy(str, "Can not download waveform when memory depth is set to \"Auto\".");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
for(i=0; i<MAX_CHNS; i++)
|
|
{
|
|
if(!devparms.chandisplay[i]) // Download data only when channel is switched on
|
|
{
|
|
continue;
|
|
}
|
|
|
|
wavbuf[i] = (short *)malloc(mempnts * sizeof(short));
|
|
if(wavbuf[i] == NULL)
|
|
{
|
|
sprintf(str, "Malloc error. line %i file %s", __LINE__, __FILE__);
|
|
goto OUT_ERROR;
|
|
}
|
|
}
|
|
|
|
tmc_write(":STOP");
|
|
|
|
usleep(20000);
|
|
|
|
for(chn=0; chn<MAX_CHNS; chn++)
|
|
{
|
|
if(!devparms.chandisplay[chn]) // Download data only when channel is switched on
|
|
{
|
|
continue;
|
|
}
|
|
|
|
sprintf(str, "Downloading channel %i waveform data...", chn + 1);
|
|
progress.setLabelText(str);
|
|
|
|
sprintf(str, ":WAV:SOUR CHAN%i", chn + 1);
|
|
|
|
tmc_write(str);
|
|
|
|
tmc_write(":WAV:FORM BYTE");
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:MODE RAW");
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:YINC?");
|
|
|
|
usleep(20000);
|
|
|
|
tmc_read();
|
|
|
|
devparms.yinc[chn] = atof(device->buf);
|
|
|
|
if(devparms.yinc[chn] < 1e-6)
|
|
{
|
|
sprintf(str, "Error, parameter \"YINC\" out of range. line %i file %s", __LINE__, __FILE__);
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:YREF?");
|
|
|
|
usleep(20000);
|
|
|
|
tmc_read();
|
|
|
|
yref[chn] = atoi(device->buf);
|
|
|
|
if((yref[chn] < 1) || (yref[chn] > 255))
|
|
{
|
|
sprintf(str, "Error, parameter \"YREF\" out of range. line %i file %s", __LINE__, __FILE__);
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:YOR?");
|
|
|
|
usleep(20000);
|
|
|
|
tmc_read();
|
|
|
|
devparms.yor[chn] = atoi(device->buf);
|
|
|
|
if((devparms.yor[chn] < -255) || (devparms.yor[chn] > 255))
|
|
{
|
|
sprintf(str, "Error, parameter \"YOR\" out of range. line %i file %s", __LINE__, __FILE__);
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
empty_buf = 0;
|
|
|
|
for(bytes_rcvd=0; bytes_rcvd<mempnts ;)
|
|
{
|
|
progress.setValue(bytes_rcvd);
|
|
|
|
if(progress.wasCanceled())
|
|
{
|
|
strcpy(str, "Canceled");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
sprintf(str, ":WAV:STAR %i", bytes_rcvd + 1);
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(str);
|
|
|
|
if((bytes_rcvd + SAV_MEM_BSZ) > mempnts)
|
|
{
|
|
sprintf(str, ":WAV:STOP %i", mempnts);
|
|
}
|
|
else
|
|
{
|
|
sprintf(str, ":WAV:STOP %i", bytes_rcvd + SAV_MEM_BSZ);
|
|
}
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(str);
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:DATA?");
|
|
|
|
get_data_thrd.start();
|
|
|
|
ev_loop.exec();
|
|
|
|
n = get_data_thrd.get_num_bytes_rcvd();
|
|
if(n < 0)
|
|
{
|
|
sprintf(str, "Can not read from device. line %i file %s", __LINE__, __FILE__);
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
if(n == 0)
|
|
{
|
|
sprintf(str, "No waveform data available.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
printf("received %i bytes, total %i bytes\n", n, n + bytes_rcvd);
|
|
|
|
if(n > SAV_MEM_BSZ)
|
|
{
|
|
sprintf(str, "Datablock too big for buffer. line %i file %s", __LINE__, __FILE__);
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
if(n < 1)
|
|
{
|
|
if(empty_buf++ > 100)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
empty_buf = 0;
|
|
}
|
|
|
|
for(k=0; k<n; k++)
|
|
{
|
|
if((bytes_rcvd + k) >= mempnts)
|
|
{
|
|
break;
|
|
}
|
|
|
|
wavbuf[chn][bytes_rcvd + k] = ((int)(((unsigned char *)device->buf)[k]) - yref[chn] - devparms.yor[chn]) << 5;
|
|
}
|
|
|
|
bytes_rcvd += n;
|
|
|
|
if(bytes_rcvd >= mempnts)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(bytes_rcvd < mempnts)
|
|
{
|
|
sprintf(str, "Download error. line %i file %s", __LINE__, __FILE__);
|
|
goto OUT_ERROR;
|
|
}
|
|
}
|
|
|
|
progress.reset();
|
|
|
|
for(chn=0; chn<MAX_CHNS; chn++)
|
|
{
|
|
if(!devparms.chandisplay[chn])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
sprintf(str, ":WAV:SOUR CHAN%i", chn + 1);
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(str);
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:MODE NORM");
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:STAR 1");
|
|
|
|
if(devparms.modelserie == 1)
|
|
{
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:STOP 1200");
|
|
}
|
|
else
|
|
{
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:STOP 1400");
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:POIN 1400");
|
|
}
|
|
}
|
|
|
|
if(bytes_rcvd < mempnts)
|
|
{
|
|
sprintf(str, "Download error. line %i file %s", __LINE__, __FILE__);
|
|
goto OUT_ERROR;
|
|
}
|
|
else
|
|
{
|
|
statusLabel->setText("Downloading finished");
|
|
}
|
|
|
|
new UI_wave_window(&devparms, wavbuf, this);
|
|
|
|
disconnect(&get_data_thrd, 0, 0, 0);
|
|
|
|
scrn_timer->start(devparms.screentimerival);
|
|
|
|
return;
|
|
|
|
OUT_ERROR:
|
|
|
|
disconnect(&get_data_thrd, 0, 0, 0);
|
|
|
|
progress.reset();
|
|
|
|
statusLabel->setText("Downloading aborted");
|
|
|
|
if(get_data_thrd.isRunning() == true)
|
|
{
|
|
QMessageBox w_msg_box;
|
|
w_msg_box.setIcon(QMessageBox::NoIcon);
|
|
w_msg_box.setText("Waiting for thread to finish, please wait...");
|
|
w_msg_box.setStandardButtons(QMessageBox::Abort);
|
|
|
|
connect(&get_data_thrd, SIGNAL(finished()), &w_msg_box, SLOT(accept()));
|
|
|
|
w_msg_box.exec();
|
|
}
|
|
|
|
if(progress.wasCanceled() == false)
|
|
{
|
|
QMessageBox msgBox;
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
msgBox.setText(str);
|
|
msgBox.exec();
|
|
}
|
|
|
|
for(chn=0; chn<MAX_CHNS; chn++)
|
|
{
|
|
if(!devparms.chandisplay[chn])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
sprintf(str, ":WAV:SOUR CHAN%i", chn + 1);
|
|
|
|
tmc_write(str);
|
|
|
|
tmc_write(":WAV:MODE NORM");
|
|
|
|
tmc_write(":WAV:STAR 1");
|
|
|
|
if(devparms.modelserie == 1)
|
|
{
|
|
tmc_write(":WAV:STOP 1200");
|
|
}
|
|
else
|
|
{
|
|
tmc_write(":WAV:STOP 1400");
|
|
|
|
tmc_write(":WAV:POIN 1400");
|
|
}
|
|
}
|
|
|
|
for(chn=0; chn<MAX_CHNS; chn++)
|
|
{
|
|
free(wavbuf[chn]);
|
|
wavbuf[chn] = NULL;
|
|
}
|
|
|
|
scrn_timer->start(devparms.screentimerival);
|
|
}
|
|
|
|
|
|
void UI_Mainwindow::save_wave_inspector_buffer_to_edf(struct device_settings *d_parms)
|
|
{
|
|
int i, j,
|
|
chn,
|
|
chns=0,
|
|
hdl=-1,
|
|
mempnts,
|
|
smps_per_record,
|
|
datrecs=1,
|
|
ret_stat;
|
|
|
|
char str[256],
|
|
opath[MAX_PATHLEN];
|
|
|
|
long long rec_len=0LL;
|
|
|
|
QMessageBox wi_msg_box;
|
|
|
|
save_data_thread sav_data_thrd(1);
|
|
|
|
mempnts = d_parms->acquirememdepth;
|
|
|
|
smps_per_record = mempnts;
|
|
|
|
for(i=0; i<MAX_CHNS; i++)
|
|
{
|
|
if(!d_parms->chandisplay[i])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
chns++;
|
|
}
|
|
|
|
if(!chns)
|
|
{
|
|
strcpy(str, "No active channels.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
while(smps_per_record >= (5000000 / chns))
|
|
{
|
|
smps_per_record /= 2;
|
|
|
|
datrecs *= 2;
|
|
}
|
|
|
|
rec_len = (EDFLIB_TIME_DIMENSION * (long long)mempnts) / d_parms->samplerate;
|
|
|
|
if(rec_len < 100)
|
|
{
|
|
strcpy(str, "Can not save waveforms shorter than 10 uSec.\n"
|
|
"Select a higher memory depth or a higher timebase.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
opath[0] = 0;
|
|
if(recent_savedir[0]!=0)
|
|
{
|
|
strcpy(opath, recent_savedir);
|
|
strcat(opath, "/");
|
|
}
|
|
strcat(opath, "waveform.edf");
|
|
|
|
strcpy(opath, QFileDialog::getSaveFileName(this, "Save file", opath, "EDF files (*.edf *.EDF)").toLocal8Bit().data());
|
|
|
|
if(!strcmp(opath, ""))
|
|
{
|
|
goto OUT_NORMAL;
|
|
}
|
|
|
|
get_directory_from_path(recent_savedir, opath, MAX_PATHLEN);
|
|
|
|
hdl = edfopen_file_writeonly(opath, EDFLIB_FILETYPE_EDFPLUS, chns);
|
|
if(hdl < 0)
|
|
{
|
|
strcpy(str, "Can not create EDF file.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
statusLabel->setText("Saving EDF file...");
|
|
|
|
if(edf_set_datarecord_us_duration(hdl, (rec_len / 10LL) / datrecs))
|
|
{
|
|
strcpy(str, "Can not set datarecord duration of EDF file.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
j = 0;
|
|
|
|
for(chn=0; chn<MAX_CHNS; chn++)
|
|
{
|
|
if(!d_parms->chandisplay[chn])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
edf_set_samplefrequency(hdl, j, smps_per_record);
|
|
edf_set_digital_maximum(hdl, j, 32767);
|
|
edf_set_digital_minimum(hdl, j, -32768);
|
|
if(d_parms->chanscale[chn] > 2)
|
|
{
|
|
edf_set_physical_maximum(hdl, j, d_parms->yinc[chn] * 32767.0 / 32.0);
|
|
edf_set_physical_minimum(hdl, j, d_parms->yinc[chn] * -32768.0 / 32.0);
|
|
edf_set_physical_dimension(hdl, j, "V");
|
|
}
|
|
else
|
|
{
|
|
edf_set_physical_maximum(hdl, j, 1000.0 * d_parms->yinc[chn] * 32767.0 / 32.0);
|
|
edf_set_physical_minimum(hdl, j, 1000.0 * d_parms->yinc[chn] * -32768.0 / 32.0);
|
|
edf_set_physical_dimension(hdl, j, "mV");
|
|
}
|
|
sprintf(str, "CHAN%i", chn + 1);
|
|
edf_set_label(hdl, j, str);
|
|
|
|
j++;
|
|
}
|
|
|
|
edf_set_equipment(hdl, d_parms->modelname);
|
|
|
|
sav_data_thrd.init_save_memory_edf_file(d_parms, hdl, datrecs, smps_per_record, d_parms->wavebuf);
|
|
|
|
wi_msg_box.setIcon(QMessageBox::NoIcon);
|
|
wi_msg_box.setText("Saving EDF file ...");
|
|
wi_msg_box.setStandardButtons(QMessageBox::Abort);
|
|
|
|
connect(&sav_data_thrd, SIGNAL(finished()), &wi_msg_box, SLOT(accept()));
|
|
|
|
sav_data_thrd.start();
|
|
|
|
ret_stat = wi_msg_box.exec();
|
|
|
|
if(ret_stat != QDialog::Accepted)
|
|
{
|
|
strcpy(str, "Saving EDF file aborted.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
if(sav_data_thrd.get_error_num())
|
|
{
|
|
sav_data_thrd.get_error_str(str);
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
OUT_NORMAL:
|
|
|
|
disconnect(&sav_data_thrd, 0, 0, 0);
|
|
|
|
if(hdl >= 0)
|
|
{
|
|
edfclose_file(hdl);
|
|
}
|
|
|
|
if(!strcmp(opath, ""))
|
|
{
|
|
statusLabel->setText("Save file canceled.");
|
|
}
|
|
else
|
|
{
|
|
statusLabel->setText("Saved memory buffer to EDF file.");
|
|
}
|
|
|
|
return;
|
|
|
|
OUT_ERROR:
|
|
|
|
disconnect(&sav_data_thrd, 0, 0, 0);
|
|
|
|
statusLabel->setText("Saving file aborted.");
|
|
|
|
if(hdl >= 0)
|
|
{
|
|
edfclose_file(hdl);
|
|
}
|
|
}
|
|
|
|
|
|
// tmc_write(":WAV:PRE?");
|
|
//
|
|
// n = tmc_read();
|
|
//
|
|
// if(n < 0)
|
|
// {
|
|
// strcpy(str, "Can not read from device.");
|
|
// goto OUT_ERROR;
|
|
// }
|
|
|
|
// printf("waveform preamble: %s\n", device->buf);
|
|
|
|
// if(parse_preamble(device->buf, device->sz, &wfp, i))
|
|
// {
|
|
// strcpy(str, "Preamble parsing error.");
|
|
// goto OUT_ERROR;
|
|
// }
|
|
|
|
// printf("waveform preamble:\n"
|
|
// "format: %i\n"
|
|
// "type: %i\n"
|
|
// "points: %i\n"
|
|
// "count: %i\n"
|
|
// "xincrement: %e\n"
|
|
// "xorigin: %e\n"
|
|
// "xreference: %e\n"
|
|
// "yincrement: %e\n"
|
|
// "yorigin: %e\n"
|
|
// "yreference: %e\n",
|
|
// wfp.format, wfp.type, wfp.points, wfp.count,
|
|
// wfp.xincrement[i], wfp.xorigin[i], wfp.xreference[i],
|
|
// wfp.yincrement[i], wfp.yorigin[i], wfp.yreference[i]);
|
|
|
|
// rec_len = wfp.xincrement[i] * wfp.points;
|
|
|
|
|
|
|
|
|
|
|
|
void UI_Mainwindow::save_screen_waveform()
|
|
{
|
|
int i, j,
|
|
n=0,
|
|
chn,
|
|
chns=0,
|
|
hdl=-1,
|
|
yref[MAX_CHNS];
|
|
|
|
char str[128],
|
|
opath[MAX_PATHLEN];
|
|
|
|
short *wavbuf[MAX_CHNS];
|
|
|
|
long long rec_len=0LL;
|
|
|
|
if(device == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for(i=0; i<MAX_CHNS; i++)
|
|
{
|
|
wavbuf[i] = NULL;
|
|
}
|
|
|
|
save_data_thread get_data_thrd(0);
|
|
|
|
QMessageBox w_msg_box;
|
|
w_msg_box.setIcon(QMessageBox::NoIcon);
|
|
w_msg_box.setText("Downloading data...");
|
|
w_msg_box.setStandardButtons(QMessageBox::Abort);
|
|
|
|
scrn_timer->stop();
|
|
|
|
scrn_thread->wait();
|
|
|
|
if(devparms.timebasedelayenable)
|
|
{
|
|
rec_len = EDFLIB_TIME_DIMENSION * devparms.timebasedelayscale * devparms.hordivisions;
|
|
}
|
|
else
|
|
{
|
|
rec_len = EDFLIB_TIME_DIMENSION * devparms.timebasescale * devparms.hordivisions;
|
|
}
|
|
|
|
if(rec_len < 10LL)
|
|
{
|
|
strcpy(str, "Can not save waveforms when timebase < 1uSec.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
for(chn=0; chn<MAX_CHNS; chn++)
|
|
{
|
|
if(!devparms.chandisplay[chn]) // Download data only when channel is switched on
|
|
{
|
|
continue;
|
|
}
|
|
|
|
wavbuf[chn] = (short *)malloc(WAVFRM_MAX_BUFSZ * sizeof(short));
|
|
if(wavbuf[chn] == NULL)
|
|
{
|
|
strcpy(str, "Malloc error.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
chns++;
|
|
}
|
|
|
|
if(!chns)
|
|
{
|
|
strcpy(str, "No active channels.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
for(chn=0; chn<MAX_CHNS; chn++)
|
|
{
|
|
if(!devparms.chandisplay[chn]) // Download data only when channel is switched on
|
|
{
|
|
continue;
|
|
}
|
|
|
|
usleep(20000);
|
|
|
|
sprintf(str, ":WAV:SOUR CHAN%i", chn + 1);
|
|
|
|
tmc_write(str);
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:FORM BYTE");
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:MODE NORM");
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:YINC?");
|
|
|
|
usleep(20000);
|
|
|
|
tmc_read();
|
|
|
|
devparms.yinc[chn] = atof(device->buf);
|
|
|
|
if(devparms.yinc[chn] < 1e-6)
|
|
{
|
|
sprintf(str, "Error, parameter \"YINC\" out of range. line %i file %s", __LINE__, __FILE__);
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:YREF?");
|
|
|
|
usleep(20000);
|
|
|
|
tmc_read();
|
|
|
|
yref[chn] = atoi(device->buf);
|
|
|
|
if((yref[chn] < 1) || (yref[chn] > 255))
|
|
{
|
|
sprintf(str, "Error, parameter \"YREF\" out of range. line %i file %s", __LINE__, __FILE__);
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:YOR?");
|
|
|
|
usleep(20000);
|
|
|
|
tmc_read();
|
|
|
|
devparms.yor[chn] = atoi(device->buf);
|
|
|
|
if((devparms.yor[chn] < -255) || (devparms.yor[chn] > 255))
|
|
{
|
|
sprintf(str, "Error, parameter \"YOR\" out of range. line %i file %s", __LINE__, __FILE__);
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
usleep(20000);
|
|
|
|
tmc_write(":WAV:DATA?");
|
|
|
|
connect(&get_data_thrd, SIGNAL(finished()), &w_msg_box, SLOT(accept()));
|
|
|
|
get_data_thrd.start();
|
|
|
|
if(w_msg_box.exec() != QDialog::Accepted)
|
|
{
|
|
disconnect(&get_data_thrd, 0, 0, 0);
|
|
strcpy(str, "Aborted by user.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
disconnect(&get_data_thrd, 0, 0, 0);
|
|
|
|
n = get_data_thrd.get_num_bytes_rcvd();
|
|
if(n < 0)
|
|
{
|
|
strcpy(str, "Can not read from device.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
if(n > WAVFRM_MAX_BUFSZ)
|
|
{
|
|
strcpy(str, "Datablock too big for buffer.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
if(n < 16)
|
|
{
|
|
strcpy(str, "Not enough data in buffer.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
for(i=0; i<n; i++)
|
|
{
|
|
wavbuf[chn][i] = ((int)(((unsigned char *)device->buf)[i]) - yref[chn] - devparms.yor[chn]) << 5;
|
|
}
|
|
}
|
|
|
|
opath[0] = 0;
|
|
if(recent_savedir[0]!=0)
|
|
{
|
|
strcpy(opath, recent_savedir);
|
|
strcat(opath, "/");
|
|
}
|
|
strcat(opath, "waveform.edf");
|
|
|
|
strcpy(opath, QFileDialog::getSaveFileName(this, "Save file", opath, "EDF files (*.edf *.EDF)").toLocal8Bit().data());
|
|
|
|
if(!strcmp(opath, ""))
|
|
{
|
|
goto OUT_NORMAL;
|
|
}
|
|
|
|
get_directory_from_path(recent_savedir, opath, MAX_PATHLEN);
|
|
|
|
hdl = edfopen_file_writeonly(opath, EDFLIB_FILETYPE_EDFPLUS, chns);
|
|
if(hdl < 0)
|
|
{
|
|
strcpy(str, "Can not create EDF file.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
if(edf_set_datarecord_duration(hdl, rec_len / 100LL))
|
|
{
|
|
strcpy(str, "Can not set datarecord duration of EDF file.");
|
|
goto OUT_ERROR;
|
|
}
|
|
|
|
j = 0;
|
|
|
|
for(chn=0; chn<MAX_CHNS; chn++)
|
|
{
|
|
if(!devparms.chandisplay[chn])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
edf_set_samplefrequency(hdl, j, n);
|
|
edf_set_digital_maximum(hdl, j, 32767);
|
|
edf_set_digital_minimum(hdl, j, -32768);
|
|
if(devparms.chanscale[chn] > 2)
|
|
{
|
|
edf_set_physical_maximum(hdl, j, devparms.yinc[chn] * 32767.0 / 32.0);
|
|
edf_set_physical_minimum(hdl, j, devparms.yinc[chn] * -32768.0 / 32.0);
|
|
edf_set_physical_dimension(hdl, j, "V");
|
|
}
|
|
else
|
|
{
|
|
edf_set_physical_maximum(hdl, j, 1000.0 * devparms.yinc[chn] * 32767.0 / 32.0);
|
|
edf_set_physical_minimum(hdl, j, 1000.0 * devparms.yinc[chn] * -32768.0 / 32.0);
|
|
edf_set_physical_dimension(hdl, j, "mV");
|
|
}
|
|
sprintf(str, "CHAN%i", chn + 1);
|
|
edf_set_label(hdl, j, str);
|
|
|
|
j++;
|
|
}
|
|
|
|
edf_set_equipment(hdl, devparms.modelname);
|
|
|
|
for(chn=0; chn<MAX_CHNS; chn++)
|
|
{
|
|
if(!devparms.chandisplay[chn])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if(edfwrite_digital_short_samples(hdl, wavbuf[chn]))
|
|
{
|
|
strcpy(str, "A write error occurred.");
|
|
goto OUT_ERROR;
|
|
}
|
|
}
|
|
|
|
OUT_NORMAL:
|
|
|
|
if(hdl >= 0)
|
|
{
|
|
edfclose_file(hdl);
|
|
}
|
|
|
|
for(chn=0; chn<MAX_CHNS; chn++)
|
|
{
|
|
free(wavbuf[chn]);
|
|
wavbuf[chn] = NULL;
|
|
}
|
|
|
|
scrn_timer->start(devparms.screentimerival);
|
|
|
|
return;
|
|
|
|
OUT_ERROR:
|
|
|
|
if(get_data_thrd.isFinished() != true)
|
|
{
|
|
connect(&get_data_thrd, SIGNAL(finished()), &w_msg_box, SLOT(accept()));
|
|
w_msg_box.setText("Waiting for thread to finish, please wait...");
|
|
w_msg_box.exec();
|
|
}
|
|
|
|
QMessageBox msgBox;
|
|
msgBox.setIcon(QMessageBox::Critical);
|
|
msgBox.setText(str);
|
|
msgBox.exec();
|
|
|
|
if(hdl >= 0)
|
|
{
|
|
edfclose_file(hdl);
|
|
}
|
|
|
|
for(chn=0; chn<MAX_CHNS; chn++)
|
|
{
|
|
free(wavbuf[chn]);
|
|
wavbuf[chn] = NULL;
|
|
}
|
|
|
|
scrn_timer->start(devparms.screentimerival);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|