/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2015, 2016, 2017, 2018 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 . * *************************************************************************** */ #define SAV_MEM_BSZ (250000) void UI_Mainwindow::save_screenshot() { int n; char str[128], opath[MAX_PATHLEN]; QPainter painter; 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); #if QT_VERSION >= 0x050000 painter.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif 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); #if QT_VERSION >= 0x050000 painter.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif 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; isetText("Downloading data..."); for(i=0; ibuf); 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) { 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= 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; chnsetText("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; chnstart(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, datrecduration; QMessageBox wi_msg_box; save_data_thread sav_data_thrd(1); mempnts = d_parms->acquirememdepth; smps_per_record = mempnts; for(i=0; ichandisplay[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..."); datrecduration = (rec_len / 10LL) / datrecs; // printf("rec_len: %lli datrecs: %i datrecduration: %lli\n", rec_len, datrecs, datrecduration); if(datrecduration < 100LL) { if(edf_set_micro_datarecord_duration(hdl, datrecduration)) { strcpy(str, "Can not set datarecord duration of EDF file."); goto OUT_ERROR; } } else { if(edf_set_datarecord_duration(hdl, datrecduration / 10LL)) { strcpy(str, "Can not set datarecord duration of EDF file."); goto OUT_ERROR; } } j = 0; for(chn=0; chnchandisplay[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); // printf("datrecs: %i smps_per_record: %i\n", datrecs, smps_per_record); 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); } wi_msg_box.setIcon(QMessageBox::Critical); wi_msg_box.setText(str); wi_msg_box.setStandardButtons(QMessageBox::Ok); wi_msg_box.exec(); } // 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; istop(); 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; chnbuf); 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; ibuf)[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 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= 0) { edfclose_file(hdl); } for(chn=0; chnstart(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; chnstart(devparms.screentimerival); }