#include "radarParams.h" RadarParams::RadarParams( QWidget* parentCP, QWidget* parent ) : QMainWindow( parentCP ) { // Set the window title. setObjectName( "Radar Parameters" ); setWindowTitle( "Radar Parameters" ); // Initialize variables. numWaveforms = 0; // Create the group box and layouts to use in the window. QGroupBox* buttonBox = new QGroupBox( "Commands" ); QGroupBox* genParamBox = new QGroupBox( "General Radar Parameters" ); QGroupBox* ddsParamBox = new QGroupBox( "General DDS Parameters (0 minimum, 255 maximum)" ); //QGroupBox* waveShapeBox = new QGroupBox( "Waveshaping Parameters" ); QGroupBox* wfBox = new QGroupBox( "Waveform Parameters" ); QGridLayout* buttonLayout = new QGridLayout; QGridLayout* genParamLayout = new QGridLayout; QGridLayout* ddsParamLayout = new QGridLayout; //QGridLayout* waveShapeLayout = new QGridLayout; QVBoxLayout* wfLayout = new QVBoxLayout; QVBoxLayout* layout = new QVBoxLayout; // Create the buttons that will go into the button layout. createWF = new QPushButton( "Create Waveform" ); deleteWF = new QPushButton( "Delete Waveform" ); loadFile = new QPushButton( "Load Configuration File" ); saveFile = new QPushButton( "Save Configuration File" ); done = new QPushButton( "Done" ); // Add the buttons to the layout. buttonLayout->addWidget( createWF, 1, 0 ); buttonLayout->addWidget( deleteWF, 1, 1 ); buttonLayout->addWidget( loadFile, 1, 2 ); buttonLayout->addWidget( saveFile, 1, 3 ); buttonLayout->addWidget( done, 1, 4 ); // Set the button layout to be the layout in the groupbox. buttonBox->setLayout( buttonLayout ); buttonBox->setMaximumHeight( 100 ); // Create the labels and lineEdits for the general and dds fields. QString genTitles[ genFields ]; QString ddsTitles[ ddsFields ]; genTitles[ SAMPF ] = "Sample Freq (MHz)"; genTitles[ DDSF ] = "DDS Freq (MHz)"; genTitles[ PRFD ] = "PRF Desired (Hz)"; genTitles[ DDSTD ] = "DDS Trigger Delay (us)"; genTitles[ BASEP ] = "Base Pulse (us)"; genTitles[ HIENABLE ] = "H.I. Enable"; genTitles[ HIRATE ] = "H.I. Rate"; genTitles[ HIWF ] = "H.I. WF Number"; genTitles[ HIPCNT ] = "H.I. Presum Count"; genTitles[ HIRCNT ] = "H.I. Readout Count"; genTitles[ DDSMS ] = "DDS Multichip Sync"; genTitles[ TRIGDIV ] = "Out Trigger Divisor"; genTitles[ TRIGCNT ] = "Out Trigger Count"; genTitles[ TRIGINV ] = "Out Trigger Inversion"; genTitles[ PRFSRC ] = "PRF Trigger Source"; genTitles[ ADCB ] = "ADC Bypass"; for( int m = 0; m < ddsFields; ++m ) { QString num; num.setNum( m + 1 ); ddsTitles[m] = "DDS"; ddsTitles[m].append( num ); ddsTitles[m].append( "_AMPLITUDE" ); } for( int n = 0; n < genFields; ++n ) { genFieldLabels[n] = new QLabel( genTitles[n] ); genFieldLines[n] = new QLineEdit( "0" ); } for( int z = 0; z < comboFields; ++z ) { genFieldCombo[z] = new QComboBox( this ); } // Set the validators for QLineEdits. // Validator for positive doubles. QDoubleValidator* validD = new QDoubleValidator( this ); validD->setBottom( 0.0 ); genFieldLines[ SAMPF ]->setValidator( validD ); // Validator for H.I. Channel Readout Count QIntValidator* validI = new QIntValidator( 0, 8000, this ); genFieldLines[ HIRCNT ]->setValidator( validI ); // Add the general fields to the grid layout. for( int p = 0; p < ( genFields / 2 ); ++p ) { genParamLayout->addWidget( genFieldLabels[p], 1, p, Qt::AlignCenter ); genParamLayout->addWidget( genFieldLines[p], 2, p ); genParamLayout->addWidget( genFieldLabels[ p + ( genFields / 2 ) ], 3, p, Qt::AlignCenter ); genParamLayout->addWidget( genFieldLines[ p + ( genFields / 2 ) ], 4, p ); ddsFieldLabels[p] = new QLabel( ddsTitles[p] ); ddsFieldLines[p] = new QLineEdit( "0" ); ddsParamLayout->addWidget( ddsFieldLabels[p], 1, p, Qt::AlignCenter ); ddsParamLayout->addWidget( ddsFieldLines[p], 2, p ); } // Disable a field. genFieldLines[ HIRATE ]->setEnabled( false ); genFieldLines[ TRIGINV ]->hide(); genFieldLines[ PRFSRC ]->hide(); genFieldLines[ ADCB ]->hide(); genFieldLines[ HIENABLE ]->hide(); // Add comboboxes to layout. genParamLayout->addWidget( genFieldCombo[ COMBOTINV ], 4, 7 ); genParamLayout->addWidget( genFieldCombo[ COMBOPRFSRC ], 2, 2 ); genParamLayout->addWidget( genFieldCombo[ COMBOHIENABLE ], 4, 0 ); genParamLayout->addWidget( genFieldCombo[ COMBOADC ], 2, 6 ); // Add fields to the combo boxes. genFieldCombo[ COMBOTINV ]->addItem( "False" ); genFieldCombo[ COMBOTINV ]->addItem( "True" ); genFieldCombo[ COMBOPRFSRC ]->addItem( "Internal" ); genFieldCombo[ COMBOPRFSRC ]->addItem( "External" ); genFieldCombo[ COMBOHIENABLE ]->addItem( "False" ); genFieldCombo[ COMBOHIENABLE ]->addItem( "True" ); genFieldCombo[ COMBOADC ]->addItem( "False" ); genFieldCombo[ COMBOADC ]->addItem( "True" ); // Add the layouts to the groupboxes. genParamBox->setLayout( genParamLayout ); ddsParamBox->setLayout( ddsParamLayout ); // Create the labels and fields for the waveshaping parameters. /*QString waveShapeTitles[ waveShapeFields ]; for( int t = 0; t < waveShapeFields; ++t ) { waveShapeTitles[t] = "Add Loss DDS "; QString num; num.setNum( t + 1 ); waveShapeTitles[t].append( num ); waveShapeFieldLabels[t] = new QLabel( waveShapeTitles[t], this ); waveShapeFieldLines[t] = new QLineEdit( "-1" ); } waveShapeTypeLabel = new QLabel( "Window Type", this ); waveShapeTypeCombo = new QComboBox( this ); waveShapeTypeCombo->addItem( "Rectangular" ); waveShapeTypeCombo->addItem( "Hanning" ); waveShapeTypeCombo->addItem( "Tukey 20%" );*/ // Add the labels and fields to the gridbox. /*for( int u = 0; u < waveShapeFields; ++u ) { waveShapeLayout->addWidget( waveShapeFieldLabels[u], 1, u, Qt::AlignCenter ); waveShapeLayout->addWidget( waveShapeFieldLines[u], 2, u ); } waveShapeLayout->addWidget( waveShapeTypeLabel, 1, waveShapeFields, Qt::AlignCenter ); waveShapeLayout->addWidget( waveShapeTypeCombo, 2, waveShapeFields );*/ // Add the layout to the groupbox. //waveShapeBox->setLayout( waveShapeLayout ); // Create the tab bar for the waveforms and general stuff. tabWidgetWave = new QTabWidget( this ); // Add the tab bar to the layout, and then set the group box to use the layout. wfLayout->addWidget( tabWidgetWave ); wfBox->setLayout( wfLayout ); // Add the group boxes to the main layout. layout->addWidget( buttonBox ); layout->addWidget( genParamBox ); layout->addWidget( ddsParamBox ); //layout->addWidget( waveShapeBox ); layout->addWidget( wfBox ); // Set the main layout for the window. setCentralWidget( new QWidget() ); centralWidget()->setLayout( layout ); // Timer to estimate the recording speed for the first time. QTimer* recTimer = new QTimer; recTimer->setSingleShot( true ); recTimer->setInterval( 1000 ); recTimer->start(); // Connect signals to functions. connect( recTimer, SIGNAL( timeout() ), this, SLOT( displayDataRate() ) ); // Run the function after the timer finishes. connect( recTimer, SIGNAL( timeout() ), this, SLOT( emitSignals() ) ); // Emit signals for different values after the timer finishes. connect( this, SIGNAL( writeMsg( QString, int ) ), parent, SLOT( writeLog( QString, int ) ) ); // Ability to write to log. connect( this, SIGNAL( recSpeed( QString ) ), parent, SLOT( dispDataRate( QString ) ) ); // Display the estimated recording speed. connect( loadFile, SIGNAL( clicked() ), this, SLOT( readInFile() ) ); // Choose a config file to load. connect( saveFile, SIGNAL( clicked() ), this, SLOT( writeToFile() ) ); // Save to a config file. connect( createWF, SIGNAL( clicked() ), this, SLOT( addTab() ) ); // Create a new waveform tab. connect( deleteWF, SIGNAL( clicked() ), this, SLOT( deleteTab() ) ); // Delete the currently selected waveform tab. connect( done, SIGNAL( clicked() ), this, SLOT( closeWindow() ) ); // Close the window. connect( genFieldLines[ SAMPF ], SIGNAL( editingFinished() ), this, SLOT( sampFreqChange() ) ); // Sample frequency changed. connect( genFieldLines[ PRFD ], SIGNAL( editingFinished() ), this, SLOT( displayDataRate() ) ); // The Desired PRF changed. connect( genFieldLines[ HIWF ], SIGNAL( editingFinished() ), this, SLOT( hiChanChange() ) ); // H.I. channel waveform changed. connect( genFieldLines[ TRIGDIV ], SIGNAL( editingFinished() ), this, SLOT( trigDivChange() ) ); // Trigger Divisor changed. connect( this, SIGNAL( sFrequencyChanged( double ) ), parentCP, SLOT( setMaxPPS( double ) ) ); // Set a new max pps because the sample frequency changed. connect( this, SIGNAL( offsetValChanged( double ) ), parent, SLOT( offsetChanged( double ) ) ); // Set the new hardcoded offset value. connect( this, SIGNAL( tauChanged( double ) ), parent, SLOT( setTau( double ) ) ); // Set the new tau value. // Load in the default config file. initialFileLoad(); // Call functions to set some variables based on values from the default config file. hiChanChange(); } RadarParams::~RadarParams() { } void RadarParams::initialFileLoad() { QString p = QDir::currentPath(); p.append( "/radar_configs/default_radar_config.dat" ); parseFile( p ); } void RadarParams::readInFile() { // Create the file dialog to open the config file. QFileDialog fDialog(this); fDialog.setFileMode( QFileDialog::ExistingFile ); fDialog.setNameFilter( tr( "Config Data Files (*.dat)" ) ); // If the user clicks OK on a file, enter the if statement. if( fDialog.exec() ) { // Get the absolute path to the file. QStringList pathList = fDialog.selectedFiles(); QString path = pathList[0]; emit writeMsg( path, DEBUG ); // Clear the waveform tabwidget. tabWidgetWave->clear(); numWaveforms = 0; // Parse the file. parseFile( path ); // Determine the estimated record speed from the new parameters. displayDataRate(); // Emit signals for the new values. emitSignals(); } } void RadarParams::parseFile( QString path ) { // Create the file, then check if the file can be opened. QFile configFile( path ); if( configFile.open( QFile::ReadOnly ) ) // File was opened. { // Create a text stream from the file. QTextStream in( &configFile ); // Create the QString that each value will be written to. QString val = ""; // Read in the header information that does not contain any information. for( int i = 0; i < 21; ++i ) { in.readLine(); } // Read in the Sampling Frequency in.readLine(); // Read in the comment. in >> val; in >> val; val.setNum( hertzToMega( val.toDouble() ), 'f', 12 ); genFieldLines[ SAMPF ]->setText( val ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // Read in the DDS Frequency in.readLine(); // Read in the comment. in >> val; in >> val; val.setNum( hertzToMega( val.toDouble() ), 'f', 12 ); genFieldLines[ DDSF ]->setText( val ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // Read in the PRF Desired in.readLine(); // Read in the comment. in >> val; in >> val; genFieldLines[ PRFD ]->setText( val ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // PRF Trigger Delay in.readLine(); // Read in the comment. in.readLine(); // Read in the comment. in.readLine(); // Read in the comment. in >> val; in >> val; val.setNum( secToMicro( val.toDouble() ), 'g', 12 ); genFieldLines[ DDSTD ]->setText( val ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // Base Pulse Duration in.readLine(); // Read in the comment. in >> val; in >> val; val.setNum( secToMicro( val.toDouble() ), 'g', 12 ); genFieldLines[ BASEP ]->setText( val ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // High Integration Channel Enable in.readLine(); // Read in the comment. in >> val; in >> val; //genFieldLines[ HIENABLE ]->setText( val ); genFieldCombo[ COMBOHIENABLE ]->setCurrentIndex( val.toInt() ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // High Integration Channel Rate in.readLine(); // Read in the comment. in.readLine(); // Read in the comment. in.readLine(); // Read in the comment. in >> val; in >> val; genFieldLines[ HIRATE ]->setText( val ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // High Integration Channel Waveform Number in.readLine(); // Read in the comment. in >> val; in >> val; genFieldLines[ HIWF ]->setText( val ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // High Integration Channel Additional Presum Count in.readLine(); // Read in the comment. in >> val; in >> val; genFieldLines[ HIPCNT ]->setText( val ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // High Integration Channel Readout Count in.readLine(); // Read in the comment. in.readLine(); // Read in the comment. in.readLine(); // Read in the comment. in >> val; in >> val; genFieldLines[ HIRCNT ]->setText( val ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // DDS Multichip Sync Value in.readLine(); // Read in the comment. in >> val; in >> val; genFieldLines[ DDSMS ]->setText( val ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // Trigger Output Divisor in.readLine(); // Read in the comment. in >> val; in >> val; genFieldLines[ TRIGDIV ]->setText( val ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // Trigger Output High Counts in.readLine(); // Read in the comment. in >> val; in >> val; genFieldLines[ TRIGCNT ]->setText( val ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // Trigger Output Inversion in.readLine(); // Read in the comment. in >> val; in >> val; //genFieldLines[ TRIGINV ]->setText( val ); genFieldCombo[ COMBOTINV ]->setCurrentIndex( val.toInt() ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // Trigger Source in.readLine(); // Read in the comment. in >> val; in >> val; //genFieldLines[ PRFSRC ]->setText( val ); genFieldCombo[ COMBOPRFSRC ]->setCurrentIndex( val.toInt() ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // ADC Bypass in.readLine(); // Read in the comment. in >> val; in >> val; //genFieldLines[ ADCB ]->setText( val ); genFieldCombo[ COMBOADC ]->setCurrentIndex( val.toInt() ); in.readLine(); // Read in the blank line. in.readLine(); // Read in the blank line. // DDS Power Level Settings in.readLine(); // Read in the comment. for( int j = 0; j < 8; ++j ) { in >> val; in >> val; ddsFieldLines[j]->setText( val ); //emit writeMsg( val, NORMAL ); in.readLine(); // Read in the blank line. } in.readLine(); // Read in the blank line. // Waveform Settings in.readLine(); // Read in the comment. while( !in.atEnd() ) { // Create a new tab for the waveform. The function will increment the numWaveforms variable. WaveformParams* wfs = addTab(); // Waveform Number in >> val; in >> val; //emit writeMsg( val, NORMAL ); in.readLine(); // Read in the blank line. // Waveform Presums in >> val; in >> val; wfs->setValue( GENERALP, 0, 0, val ); in.readLine(); // Read in the blank line. // Waveform TX Mask in >> val; in >> val; wfs->setValue( GENERALP, 0, 1, val ); in.readLine(); // Read in the blank line. // Waveform Start Frequency in >> val; in >> val; val.setNum( hertzToMega( val.toDouble() ), 'g', 12 ); wfs->setValue( GENERALP, 0, 2, val ); in.readLine(); // Read in the blank line. // Waveform Stop Frequency in >> val; in >> val; val.setNum( hertzToMega( val.toDouble() ), 'g', 12 ); wfs->setValue( GENERALP, 0, 3, val ); in.readLine(); // Read in the blank line. // Waveform Zero Pi Mod in >> val; in >> val; wfs->setValue( GENERALP, 0, 4, val ); in.readLine(); // Read in the blank line. // Waveform Angle in >> val; in >> val; wfs->setValue( GENERALP, 0, 5, val ); in.readLine(); // Read in the blank line. // Waveform Length Mult in >> val; in >> val; wfs->setValue( GENERALP, 0, 6, val ); in.readLine(); // Read in the blank line. // Waveform DAQ Rec Length in >> val; in >> val; val.setNum( secToMicro( val.toDouble() ), 'g', 12 ); wfs->setValue( GENERALP, 0, 7, val ); in.readLine(); // Read in the blank line. // Waveform DAQ Rec Delay in >> val; in >> val; val.setNum( secToMicro( val.toDouble() ), 'g', 12 ); wfs->setValue( GENERALP, 0, 8, val ); in.readLine(); // Read in the blank line. // DDS Stuff ( 1 - 8 ) for( int k = 0; k < 8; ++k ) { // DDS Number in >> val; in >> val; //emit writeMsg( val, NORMAL ); in.readLine(); // Read in the blank line. // DDS Frequency Start in >> val; in >> val; wfs->setValue( DDSP, 0, k, val ); //emit writeMsg( val, NORMAL ); in.readLine(); // Read in the blank line. // DDS Phase Start Zero in >> val; in >> val; wfs->setValue( DDSP, 1, k, val ); //emit writeMsg( val, NORMAL ); in.readLine(); // Read in the blank line. // DDS Phase Start Pi in >> val; in >> val; wfs->setValue( DDSP, 2, k, val ); //emit writeMsg( val, NORMAL ); in.readLine(); // Read in the blank line. } // Pulse Out Stuff ( 0 - 7 ) for( int l = 0; l < 8; ++l ) { // Pulse Out Start Count in >> val; in >> val; wfs->setValue( PULSEP, 0, l, val ); //emit writeMsg( val, NORMAL ); in.readLine(); // Read in the blank line. // Pulse Out Width Count in >> val; in >> val; wfs->setValue( PULSEP, 1, l, val ); //emit writeMsg( val, NORMAL ); in.readLine(); // Read in the blank line. } // Attention If Stuff ( A - D ) for( int m = 0; m < 4; ++m ) { // Channel 1 Attention 1 in >> val; in >> val; wfs->setValue( ATTENTP, 0, m, val ); //emit writeMsg( val, NORMAL ); in.readLine(); // Read in the blank line. // Channel 1 Attention 2 in >> val; in >> val; wfs->setValue( ATTENTP, 1, m, val ); //emit writeMsg( val, NORMAL ); in.readLine(); // Read in the blank line. // Channel 2 Attention 2 in >> val; in >> val; wfs->setValue( ATTENTP, 2, m, val ); //emit writeMsg( val, NORMAL ); in.readLine(); // Read in the blank line. // Channel 2 Attention 2 in >> val; in >> val; wfs->setValue( ATTENTP, 3, m, val ); //emit writeMsg( val, NORMAL ); in.readLine(); // Read in the blank line. } in.readLine(); // Read in the blank line. } configFile.close(); } } void RadarParams::writeToFile() { // Create the file dialog to find the file to save. QFileDialog fDialog(this); fDialog.setAcceptMode( QFileDialog::AcceptSave ); fDialog.setNameFilter( tr( "Config Data Files (*.dat)" ) ); fDialog.setDefaultSuffix( tr( "dat" ) ); // If the user clicks OK on a file, enter the if statement. if( fDialog.exec() ) { // Get the absolute path to the file. QStringList pathList = fDialog.selectedFiles(); QString path = pathList[0]; emit writeMsg( path, DEBUG ); generateOutput( path ); } } void RadarParams::generateOutput( QString path ) { // Create QFile object and open the file as write-only. QFile configFile( path ); if( configFile.open( QFile::WriteOnly | QFile::Truncate ) ) // File opened properly. { // Create the QTextStream to make it easy to write out to the file. QTextStream out( &configFile ); out.setRealNumberPrecision( 15 ); // Write out the header comments. out << "#############################################\n"; out << "# Configurations File for CReSIS Radars\n"; out << "#\n"; out << "# University of Kansas\n"; out << "# CReSIS\n"; out << "# 2335 Irving Hill Rd.\n"; out << "# Lawrence, KS 66045\n"; out << "# https://www.cresis.ku.edu/\n"; out << "#############################################\n"; out << "# Comment lines are from the pound sign to \n"; out << "# the end of the line\n"; out << "#############################################\n"; out << "#\n"; out << "# This file is generated automatically.\n"; out << "# It is recommended that you not hand edit\n"; out << "# this file. But it is written in human readable\n"; out << "# format on purpose, just in case.\n"; out << "#\n"; out << "#############################################\n\n\n"; // Write Sampling Frequency out << "# Sampling frequency, in Hertz.\n"; out << "SAMPLE_FREQUENCY " << megaToHertz( genFieldLines[ SAMPF ]->text().toDouble() ) << "\n\n"; // DDS Frequency out << "# DDS frequency, in Hertz.\n"; out << "DDS_FREQUENCY " << megaToHertz( genFieldLines[ DDSF ]->text().toDouble() ) << "\n\n"; // PRF out << "# PRF Desired, in Hertz\n"; out << "PRF " << genFieldLines[ PRFD ]->text() << "\n\n"; // IO Update Time out << "# Delay from PRF Trigger, until the waveform starts coming out.\n"; out << "# In Seconds. Must be larger than 10.4 us to allow for updating\n"; out << "# the AD9910 in time.\n"; out << "IO_UPDATE_TIME " << microToSec( genFieldLines[ DDSTD ]->text().toDouble() ) << "\n\n"; // Base Pulse Duration out << "# Base Pulse Duration\n"; out << "BASE_PULSE_LENGTH " << microToSec( genFieldLines[ BASEP ]->text().toDouble() ) << "\n\n"; // High Integration Channel Enable out << "# High Integration Channel Enable: 1=on, 0=off\n"; out << "HI_CH_ENA " << genFieldCombo[ COMBOHIENABLE ]->currentIndex() << "\n\n"; // High Integration Channel Rate out << "# High Integration Channel rate setting\n"; out << "# The waveform generator will trigger a new HI cycle\n"; out << "# every number of EPRI cycles\n"; out << "HI_CH_RATE " << genFieldLines[ HIRATE ]->text() << "\n\n"; // High Integration Channel Waveform Number out << "# High Integration Channel Waveform Number\n"; out << "HI_CH_WFNUM " << genFieldLines[ HIWF ]->text() << "\n\n"; // High Integration Channel Additional Presum Count out << "# High Integration Channel Additional Presum Count\n"; out << "HI_CH_PRE_CNT " << genFieldLines[ HIPCNT ]->text() << "\n\n"; // High Integration Channel Readout Count out << "# High Integration Channel Readout Count\n"; out << "# This is the number of double-sample readouts\n"; out << "# e.g. a setting of 5 will read out 10 samples\n"; out << "HI_CH_RO_CNT " << genFieldLines[ HIRCNT ]->text() << "\n\n"; // DDS Multichip Sync Value out << "# DDS Multichip Sync Value\n"; out << "MULTICHIP_SYNC " << genFieldLines[ DDSMS ]->text() << "\n\n"; // Trigger Output Divisor out << "# Trigger Output Divisor\n"; out << "TRIG_OUT_DIV " << genFieldLines[ TRIGDIV ]->text() << "\n\n"; // Trigger Output High Counts out << "# Trigger Output High Counts\n"; out << "TRIG_OUT_CNT_HIGH " << genFieldLines[ TRIGCNT ]->text() << "\n\n"; // Trigger Output Inversion out << "# Trigger Output Inversion: 0 = Active High, 1 = Active Low\n"; out << "TRIG_OUT_INV " << genFieldCombo[ COMBOTINV ]->currentIndex() << "\n\n"; // Trigger Source out << "# Trigger Source: 0 = Internal, 1 = External Trigger Mode\n"; out << "TRIG_SOURCE " << genFieldCombo[ COMBOPRFSRC ]->currentIndex() << "\n\n"; // ADC Bypass out << "# ADC Bypass: 0 = ADC / Normal mode, 1 = internal ramp mode\n"; out << "ADC_BYPASS " << genFieldCombo[ COMBOADC ]->currentIndex() << "\n\n"; // Write the DDS Values out << "# DDS Power Level Settings\n"; for( int i = 0; i < 8; ++i ) { QString label = "DDS"; QString num; num.setNum( i + 1 ); label.append( num ); label.append( "_AMPLITUDE " ); out << label << ddsFieldLines[i]->text() << "\n"; } out << "\n"; // Write out the values for each waveform. out << "# Waveform Settings\n"; for( int j = 0; j < numWaveforms; ++j ) { // Get the WaveformParams object from the QTabWidget to get the correct values. WaveformParams* curWf = (WaveformParams*)tabWidgetWave->widget( j ); // Waveform general parameters. QString wfNum; wfNum.setNum( j + 1 ); out << "WAVEFORM " << wfNum << "\n"; out << " WAVEFORM_PRESUMS " << curWf->getValue( GENERALP, 0, 0 ) << "\n"; out << " WAVEFORM_TX_MASK " << curWf->getValue( GENERALP, 0, 1 ) << "\n"; out << " WAVEFORM_START_FREQ " << megaToHertz( curWf->getValue( GENERALP, 0, 2 ).toDouble() ) << "\n"; out << " WAVEFORM_STOP_FREQ " << megaToHertz( curWf->getValue( GENERALP, 0, 3 ).toDouble() ) << "\n"; out << " WAVEFORM_ZERO_PI_MOD " << curWf->getValue( GENERALP, 0, 4 ) << "\n"; out << " WAVEFORM_ANGLE " << curWf->getValue( GENERALP, 0, 5 ) << "\n"; out << " WAVEFORM_LENGTH_MULT " << curWf->getValue( GENERALP, 0, 6 ) << "\n"; out << " WAVEFORM_DAQ_REC_LENGTH " << microToSec( curWf->getValue( GENERALP, 0, 7 ).toDouble() ) << "\n"; out << " WAVEFORM_DAQ_REC_DELAY " << microToSec( curWf->getValue( GENERALP, 0, 8 ).toDouble() ) << "\n"; // DDS parameters for( int k = 0; k < 8; ++k ) { QString ddsNum; ddsNum.setNum( k + 1 ); out << " DDS " << ddsNum << "\n"; out << " DDS_FREQ_START " << curWf->getValue( DDSP, 0, k ) << "\n"; out << " DDS_PHASE_START_ZERO " << curWf->getValue( DDSP, 1, k ) << "\n"; out << " DDS_PHASE_START_PI " << curWf->getValue( DDSP, 2, k ) << "\n"; } // Pulse Out Counts for( int l = 0; l < 8; ++l ) { QString poNum; poNum.setNum( l ); out << " PULSE_OUT_" << poNum << "_START_CNT " << curWf->getValue( PULSEP, 0, l ) << "\n"; out << " PULSE_OUT_" << poNum << "_WIDTH_CNT " << curWf->getValue( PULSEP, 1, l ) << "\n"; } // Attention Ifs out << " ATTEN_IF_A_CH1_ATTEN1 " << curWf->getValue( ATTENTP, 0, 0 ) << "\n"; out << " ATTEN_IF_A_CH1_ATTEN2 " << curWf->getValue( ATTENTP, 1, 0 ) << "\n"; out << " ATTEN_IF_A_CH2_ATTEN1 " << curWf->getValue( ATTENTP, 2, 0 ) << "\n"; out << " ATTEN_IF_A_CH2_ATTEN2 " << curWf->getValue( ATTENTP, 3, 0 ) << "\n"; out << " ATTEN_IF_B_CH1_ATTEN1 " << curWf->getValue( ATTENTP, 0, 1 ) << "\n"; out << " ATTEN_IF_B_CH1_ATTEN2 " << curWf->getValue( ATTENTP, 1, 1 ) << "\n"; out << " ATTEN_IF_B_CH2_ATTEN1 " << curWf->getValue( ATTENTP, 2, 1 ) << "\n"; out << " ATTEN_IF_B_CH2_ATTEN2 " << curWf->getValue( ATTENTP, 3, 1 ) << "\n"; out << " ATTEN_IF_C_CH1_ATTEN1 " << curWf->getValue( ATTENTP, 0, 2 ) << "\n"; out << " ATTEN_IF_C_CH1_ATTEN2 " << curWf->getValue( ATTENTP, 1, 2 ) << "\n"; out << " ATTEN_IF_C_CH2_ATTEN1 " << curWf->getValue( ATTENTP, 2, 2 ) << "\n"; out << " ATTEN_IF_C_CH2_ATTEN2 " << curWf->getValue( ATTENTP, 3, 2 ) << "\n"; out << " ATTEN_IF_D_CH1_ATTEN1 " << curWf->getValue( ATTENTP, 0, 3 ) << "\n"; out << " ATTEN_IF_D_CH1_ATTEN2 " << curWf->getValue( ATTENTP, 1, 3 ) << "\n"; out << " ATTEN_IF_D_CH2_ATTEN1 " << curWf->getValue( ATTENTP, 2, 3 ) << "\n"; out << " ATTEN_IF_D_CH2_ATTEN2 " << curWf->getValue( ATTENTP, 3, 3 ) << "\n\n"; } } } void RadarParams::generateBinOutput( QString path ) { // Open the file for writing binary. char bin[128]; sprintf( bin, path.toStdString().c_str() ); FILE* binFile = fopen( bin, "wb" ); float val = 0.0; // Write the values in the general fields. for( int i = 0; i < genFields; ++i ) { val = genFieldLines[i]->text().toFloat(); fwrite( &val, sizeof( float ), 1, binFile ); } // Write the values in the dds fields. for( int j = 0; j < ddsFields; ++j ) { val = ddsFieldLines[j]->text().toFloat(); fwrite( &val, sizeof( float ), 1, binFile ); } // Write the values for each waveform. for( int k = 0; k < numWaveforms; ++k ) { // Get the WaveformParams object from the QTabWidget to get the correct values. WaveformParams* curWf = (WaveformParams*)tabWidgetWave->widget( k ); // Write out the general waveform values (including the waveform number) val = k + 1.0; fwrite( &val, sizeof( float ), 1, binFile ); // Waveform number for( int m = 0; m < 9; ++m ) { val = curWf->getValue( GENERALP, 0, m ).toFloat(); fwrite( &val, sizeof( float ), 1, binFile ); // General params. } // Write out DDS params. for( int n = 0; n < 8; ++n ) { val = n + 1; fwrite( &val, sizeof( float ), 1, binFile ); // DDS number. val = curWf->getValue( DDSP, 0, n ).toFloat(); fwrite( &val, sizeof( float ), 1, binFile ); // Start val = curWf->getValue( DDSP, 1, n ).toFloat(); fwrite( &val, sizeof( float ), 1, binFile ); // Zero val = curWf->getValue( DDSP, 2, n ).toFloat(); fwrite( &val, sizeof( float ), 1, binFile ); // Pi } // Write out write out counts. for( int p = 0; p < 8; ++p ) { val = curWf->getValue( PULSEP, 0, p ).toFloat(); // Start Count fwrite( &val, sizeof( float ), 1, binFile ); val = curWf->getValue( PULSEP, 0, p ).toFloat(); // Width Count fwrite( &val, sizeof( float ), 1, binFile ); } // Write out attention params. for( int q = 0; q < 4; ++q ) // A to D { for( int r = 0; r < 4; ++r ) // CH1-1, CH1-2, CH2-1, CH2-2 { val = curWf->getValue( ATTENTP, r, q ).toFloat(); fwrite( &val, sizeof( float ), 1, binFile ); } } } fflush( binFile ); fclose( binFile ); } void RadarParams::closeEvent( QCloseEvent* event ) { emit writeMsg( ">Finished Radar Parameter Configuration", NORMAL ); event->accept(); } void RadarParams::writeToLog( QString text, int type ) { emit writeMsg( text, type ); } void RadarParams::valuesChanged( int table ) { QString t; t.setNum( table ); emit writeMsg( "A value has been changed in table " + t, DEBUG ); } void RadarParams::deleteTab() { // Get the current tab's index. int index = tabWidgetWave->currentIndex(); // Remove the currently selected tab. tabWidgetWave->removeTab( index ); // Decrement the waveform number. numWaveforms--; if( numWaveforms > 0 ) { // Change the title of the remaining tabs after the one that was deleted to match their new numbers. for( int i = index; i < numWaveforms; ++i ) { // Create the QString to be the title. QString title = "Waveform "; QString num; num.setNum( i + 1 ); title.append( num ); // Set the tab to use the new title. tabWidgetWave->setTabText( i, title ); } } else { addTab(); } // Check if the H.I. channel select is higher than the current waveforms. if( genFieldLines[ HIWF ]->text().toInt() > numWaveforms ) { QString value; value.setNum( numWaveforms ); genFieldLines[ HIWF ]->setText( value ); } } WaveformParams* RadarParams::addTab() { // Increment the number of waveforms. numWaveforms++; // Create the title of the waveform to display on the tab. QString title = "Waveform "; QString num; num.setNum( numWaveforms ); title.append( num ); // Create a new WaveformParams object. WaveformParams* newObj; if( ( numWaveforms - 1) > 0 ) { newObj = new WaveformParams( numWaveforms, (WaveformParams*)tabWidgetWave->widget( tabWidgetWave->currentIndex() ), this ); } else { newObj = new WaveformParams( numWaveforms, NULL, this ); } // Add the new tab to the tabWidget. tabWidgetWave->addTab( newObj, title ); // Set the new waveform to be the selected tab. tabWidgetWave->setCurrentIndex( numWaveforms - 1 ); // Return the pointer to the new object in the tab. return newObj; } void RadarParams::sampFreqChange() { // Generate the new DDS Frequency double sFreq = megaToHertz( genFieldLines[ SAMPF ]->text().toDouble() ); double dFreq = ( sFreq / 2.0 ) * 16.0; QString ddsFreq; ddsFreq.setNum( hertzToMega( dFreq ), 'f', 16 ); genFieldLines[ DDSF ]->setText( ddsFreq ); // Determine the Multichip Sync QString mChip; if( ( sFreq > 111111111.09 ) && ( sFreq < 111111111.13 ) ) { mChip.setNum( 20 ); genFieldLines[ DDSMS ]->setText( mChip ); } else if( ( sFreq > 124999999.98 ) && ( sFreq < 125000000.02) ) { mChip.setNum( 18 ); genFieldLines[ DDSMS ]->setText( mChip ); } else { mChip.setNum( 20 ); genFieldLines[ DDSMS ]->setText( mChip ); } // Recaclulate the data rate. displayDataRate(); // Emit signal that the sample frequency was changed. emit sFrequencyChanged( sFreq ); } void RadarParams::displayDataRate() { // Form the string to display. QString estRecSpeed, msg; estRecSpeed.setNum( findDataRate(), 'f', 1 ); // Precision of 3 places. msg = "Estimated Recording Speed: "; //estRecSpeed.append( " MB/s" ); msg.append( estRecSpeed ); msg.append( " MB/s" ); // Display the message in the Radar Parameter Configuration window in the status bar. statusBar()->showMessage( msg ); // Display the message in the HDD Status section of the Control Panel. emit recSpeed( estRecSpeed ); } double RadarParams::findDataRate() { // Initialize variables. double sampFreq = megaToHertz( genFieldLines[ SAMPF ]->text().toDouble() ); int desiredPRF = genFieldLines[ PRFD ]->text().toInt(); unsigned int bytesPerEPRI = 0; //double timePerEPRI = 0.0; double dataRate = 0.0; int countEPRI = 0; // Iterate through the waveforms. for( int i = 0; i < numWaveforms; ++i ) { // Get the waveform object. WaveformParams* curWf = (WaveformParams*)tabWidgetWave->widget( i ); // Get the DAQ Rec Length value. QString tmp = curWf->getValue( GENERALP, 0, 7 ); double daqRecLength = microToSec( tmp.toDouble() ); // Get the Presums value. int presums = curWf->getValue( GENERALP, 0, 0 ).toInt(); // Add this waveform's presums to the other presums. countEPRI += presums; // Determine the byteCount and add it to the other waveform's byteCounts. unsigned int byteCount = daqRecLength * sampFreq * 2.0; bytesPerEPRI += byteCount; curWf = NULL; } QString tmpConfigPath = QDir::currentPath(); tmpConfigPath.append( "/radar_configs/config_radar.txt" ); generateOutput( tmpConfigPath ); // Take the desired PRF, convert it into counts, do some rounding, and then convert it back into Hz. int countPRF = desiredPRF; countPRF = sampFreq / ( 2 * countPRF ); // Desired PRF into counts. countPRF /= 64; // Rounding. countPRF *= 64;// Rounding. double actualPRF = ( sampFreq / ( 2.0 * countPRF ) ); // PRF counts into Hz double effectivePRF = actualPRF / (double)countEPRI; // The effective PRF. // Find the data rate. dataRate = bytesPerEPRI * effectivePRF; // B/s dataRate = dataRate / 1048576.0; // MB/s return dataRate; } void RadarParams::hiChanChange() { if( ( genFieldLines[ HIWF ]->text().toInt() < 1 ) || ( genFieldLines[ HIWF ]->text().toInt() > numWaveforms ) ) { QString newVal; newVal.setNum( 1 ); genFieldLines[ HIWF ]->setText( newVal ); } double basePulse = microToSec( genFieldLines[ BASEP ]->text().toDouble() ); int index = genFieldLines[ HIWF ]->text().toInt() - 1; WaveformParams* wf = (WaveformParams*)tabWidgetWave->widget( index ); double t_lengthMult = wf->getValue( GENERALP, 0, 6 ).toDouble(); f0 = megaToHertz( wf->getValue( GENERALP, 0, 2 ).toDouble() ); // Start frequency. f1 = megaToHertz( wf->getValue( GENERALP, 0, 3 ).toDouble() ); // Stop frequency. tau = basePulse * t_lengthMult; // Chirp rate. emit tauChanged( tau * 1000000.0 ); wf = NULL; offsetChange(); } void RadarParams::wfFreqChange() { int index = tabWidgetWave->currentIndex(); WaveformParams* wf = (WaveformParams*)tabWidgetWave->widget( index ); // Initialize variables. double sampFreq = megaToHertz( genFieldLines[ SAMPF ]->text().toDouble() ); double basePulse = microToSec( genFieldLines[ BASEP ]->text().toDouble() ); double t_lengthMult = wf->getValue( GENERALP, 0, 6 ).toDouble(); double t_f0 = megaToHertz( wf->getValue( GENERALP, 0, 2 ).toDouble() ); double t_f1 = megaToHertz( wf->getValue( GENERALP, 0, 3 ).toDouble() ); double t_angle = wf->getValue( GENERALP, 0, 5 ).toDouble(); double clk = ( sampFreq / 2.0 ) * 16.0; double t_tau = basePulse * t_lengthMult; double t_tstep = 4.0 / clk; double t_fstep = ( t_f1 - t_f0 ) * ( t_tstep / t_tau ); long int t_fstep_32bit = lround( pow( 2.0, 32.0 ) * t_fstep / clk ); double t_fstep_actual = clk * ( t_fstep_32bit / pow( 2.0, 32.0 ) ); double t_chirpRate = t_fstep_actual / t_tstep; // Variables to be calculated below. double xc; double tshift; double f0_adj; long int f0_adj_32bit; // Calculate the required values. for( int i = 0; i < 8; ++i ) { xc = i * 0.75; tshift = ( -xc ) * sin( t_angle * M_PI / 180.0 ) / 300000000.0; f0_adj = t_f0 + tshift * t_chirpRate; f0_adj_32bit = lround( pow( 2.0, 32.0 ) * f0_adj / clk ); // Set the DDS Start Frequency value. QString val; val.setNum( f0_adj_32bit ); wf->setValue( DDSP, 0, i, val ); } } ProcParams* RadarParams::getProcessingValues() { // Create the object and set the variables of the object. ProcParams* p = new ProcParams; p->f0 = f0; p->f1 = f1; p->tau = tau; p->sFrequency = megaToHertz( genFieldLines[ SAMPF ]->text().toDouble() ); p->pLength = microToSec( genFieldLines[ BASEP ]->text().toDouble() ); p->rCount = genFieldLines[ HIRCNT ]->text().toInt(); // Return the object. return p; } void RadarParams::offsetChange() { double off = 0.0; int index = genFieldLines[ HIWF ]->text().toInt() - 1; WaveformParams* wf = (WaveformParams*)tabWidgetWave->widget( index ); off = microToSec( wf->getValue( GENERALP, 0, 8 ).toDouble() ); // Get the H.I. channel waveform's DAQ record delay. off = off - microToSec( genFieldLines[ DDSTD ]->text().toDouble() ); // Subtract the radar's trigger delay. off = off * 1000000.0; // Multiply by the number of microseconds in a second to conver seconds to microseconds. QString val; val.setNum( off ); val.prepend( "Time offset value calculated from Record Delay - Trigger Delay: " ); emit writeMsg( val , DEBUG ); emit offsetValChanged( off ); // Send the offset, which is in us. wf = NULL; } void RadarParams::emitSignals() { emit sFrequencyChanged( megaToHertz( genFieldLines[ SAMPF ]->text().toDouble() ) ); // New sample frequency. } void RadarParams::closeWindow() { QString tmpConfigPath = QDir::currentPath(); QString tmpBinPath = QDir::currentPath(); tmpConfigPath.append( "/radar_configs/config_radar.txt" ); tmpBinPath.append( "/radar_configs/config_radar.bin" ); generateOutput( tmpConfigPath ); generateBinOutput( tmpBinPath ); this->close(); } double RadarParams::hertzToMega( double hz ) { return hz / 1000000.0; } double RadarParams::megaToHertz( double mhz ) { return mhz * 1000000.0; } double RadarParams::secToMicro( double sec ) { return sec * 1000000.0; } double RadarParams::microToSec( double micro ) { return micro / 1000000.0; } void RadarParams::trigDivChange() { if( genFieldLines[ TRIGDIV ]->text().toInt() < 2 ) { QString val; val.setNum( 2 ); genFieldLines[ TRIGDIV ]->setText( val ); } }