diff --git a/Desktop_Interface/Labrador.pro b/Desktop_Interface/Labrador.pro index 89673fc7..c656eba1 100644 --- a/Desktop_Interface/Labrador.pro +++ b/Desktop_Interface/Labrador.pro @@ -39,7 +39,8 @@ SOURCES += main.cpp\ isobufferbuffer.cpp \ uartstyledecoder.cpp \ daqform.cpp \ - daqloadprompt.cpp + daqloadprompt.cpp \ + isobuffer_file.cpp HEADERS += mainwindow.h \ functiongencontrol.h \ @@ -54,7 +55,8 @@ HEADERS += mainwindow.h \ unified_debug_structure.h \ uartstyledecoder.h \ daqform.h \ - daqloadprompt.h + daqloadprompt.h \ + isobuffer_file.h android:{ FORMS += ui_files_mobile/mainwindow.ui \ diff --git a/Desktop_Interface/daqloadprompt.cpp b/Desktop_Interface/daqloadprompt.cpp index ffe30a41..c1747425 100644 --- a/Desktop_Interface/daqloadprompt.cpp +++ b/Desktop_Interface/daqloadprompt.cpp @@ -1,6 +1,7 @@ #include "daqloadprompt.h" #include "ui_daqloadprompt.h" #include +#include "siprint.h" daqLoadPrompt::daqLoadPrompt(QWidget *parent, double minTime, double maxTime) : QDialog(parent), @@ -13,11 +14,14 @@ daqLoadPrompt::daqLoadPrompt(QWidget *parent, double minTime, double maxTime) : ui->endTimeDoubleSpinBox->setMinimum(minTime); ui->startTimeDoubleSpinBox->setMaximum(maxTime); ui->endTimeDoubleSpinBox->setMaximum(maxTime); + ui->startTimeDoubleSpinBox->setValue(minTime); + ui->endTimeDoubleSpinBox->setValue(maxTime); //Internal signals connect(ui->startTimeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(valueChange())); connect(ui->endTimeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(valueChange())); + valueChange(); } daqLoadPrompt::~daqLoadPrompt() @@ -31,4 +35,11 @@ void daqLoadPrompt::valueChange(){ startTime(ui->startTimeDoubleSpinBox->value()); endTime(ui->endTimeDoubleSpinBox->value()); + + double contig_ram_required = ((ui->endTimeDoubleSpinBox->value() - ui->startTimeDoubleSpinBox->value()) / min_interval) * 4 + 512; //4 bytes per sample (float), each sample is stored only once. 512 is just a bullshit value to represent the overhead required to store the other variables in the buffer object + siprint cotig_print("B",contig_ram_required); + + ui->contigRamLabel_Value->setText(cotig_print.printVal()); + + } diff --git a/Desktop_Interface/isobuffer.cpp b/Desktop_Interface/isobuffer.cpp index 93f0c31c..7ef48e40 100644 --- a/Desktop_Interface/isobuffer.cpp +++ b/Desktop_Interface/isobuffer.cpp @@ -300,7 +300,7 @@ short isoBuffer::inverseSampleConvert(double voltageLevel, int TOP, bool AC){ #define X1_X2_COMPARISON_CAP > #endif - +//For capacitance measurement. x0, x1 and x2 are all various time points used to find the RC coefficient. int isoBuffer::cap_x0fromLast(double seconds, double vbot){ int samplesInPast = seconds * samplesPerSecond; if(back < samplesInPast){ diff --git a/Desktop_Interface/isobuffer_file.cpp b/Desktop_Interface/isobuffer_file.cpp new file mode 100644 index 00000000..5c73c625 --- /dev/null +++ b/Desktop_Interface/isobuffer_file.cpp @@ -0,0 +1,82 @@ +#include "isobuffer_file.h" +#include "math.h" +#include + +isoBuffer_file::isoBuffer_file(QWidget *parent, int bufferlen, double sampleRate_Hz) : QWidget(parent) +{ + buffer = (float *) calloc(bufferlen, sizeof(float)); + bufferEnd = bufferlen-1; + samplesPerSecond = sampleRate_Hz; +} + +void isoBuffer_file::writeBuffer_float(float* data, int len) +{ + for (int i=0; i (double) front){ + qDebug() << "Wrap!"; + accumulatedDelay -= (double) front; + front = bufferEnd; + } + + idx = (int) round(((double) front - accumulatedDelay)); + if (idx < 0){ + qDebug() << "Wrap"; + accumulatedDelay--; + accumulatedDelay -= (double) front; + front = bufferEnd; + idx = (int) round(((double) front - accumulatedDelay)); + } + readData[i] = buffer[idx]; + accumulatedDelay += timeBetweenSamples; + } + } + + return readData; +} + +void isoBuffer_file::clearBuffer() +{ + for (int i=0; i +#include "xmega.h" + +class isoBuffer_file : public QWidget +{ + Q_OBJECT +public: + explicit isoBuffer_file(QWidget *parent, int bufferlen, double sampleRate_Hz); + + //Required Functions + void writeBuffer_float(float* data, int len); + float *readBuffer(double sampleWindow, int numSamples, bool singleBit, double delayOffset); + void clearBuffer(); + double samplesPerSecond; + int bufferEnd, back = 0; + float *buffer, *readData = NULL; +signals: + +public slots: +}; + +#endif // ISOBUFFER_FILE_H diff --git a/Desktop_Interface/isodriver.cpp b/Desktop_Interface/isodriver.cpp index 255f7368..54dbf74e 100644 --- a/Desktop_Interface/isodriver.cpp +++ b/Desktop_Interface/isodriver.cpp @@ -1,5 +1,6 @@ #include "isodriver.h" #include "isobuffer.h" +#include "isobuffer_file.h" #include "platformspecific.h" #include #include "daqloadprompt.h" @@ -61,6 +62,11 @@ void isoDriver::timerTick(void){ //qDebug() << length << "read in!!"; total_read += length; + if(fileModeEnabled){ + qDebug() << "File mode is active. Abort live refresh"; + return; + } + if (length==0){ //Zero length packet means something's gone wrong. Probably a disconnect. qDebug() << "Zero length iso packet!"; @@ -170,6 +176,14 @@ void isoDriver::digitalConvert(short *shortPtr, QVector *doublePtr){ //cool_waveform = cool_waveform - AC_offset; } +void isoDriver::fileStreamConvert(float *floatPtr, QVector *doublePtr){ + double *data = doublePtr->data(); + for (int i=0;imodifiers() == Qt::ControlModifier)){ double c = (topRange - botRange) / (double)400; @@ -243,8 +257,10 @@ void isoDriver::setVoltageRange(QWheelEvent *event){ delay -= c* ((double)100 - (double)pixPct) * pixPct/100; } - if (window > (double)MAX_WINDOW_SIZE) window = (double)MAX_WINDOW_SIZE; - if ((window + delay) > MAX_WINDOW_SIZE) delay -= window + delay - (double)MAX_WINDOW_SIZE; + double mws = fileModeEnabled ? daq_maxWindowSize : ((double)MAX_WINDOW_SIZE); + + if (window > mws) window = mws; + if ((window + delay) > mws) delay -= window + delay - mws; if (delay < 0) delay = 0; qDebug() << window << delay; } else { @@ -273,8 +289,10 @@ void isoDriver::setVoltageRange(QWheelEvent *event){ delay -= c* ((double)100 - (double)pixPct) * pixPct/100; } - if (window > (double)MAX_WINDOW_SIZE) window = (double)MAX_WINDOW_SIZE; - if ((window + delay) > MAX_WINDOW_SIZE) delay -= window + delay - (double)MAX_WINDOW_SIZE; + double mws = fileModeEnabled ? daq_maxWindowSize : ((double)MAX_WINDOW_SIZE); + + if (window > mws) window = mws; + if ((window + delay) > mws) delay -= window + delay - mws; if (delay < 0) delay = 0; windowAtPause = window; qDebug() << window << delay; @@ -633,7 +651,7 @@ void isoDriver::setTriggerMode(int newMode){ triggerType = (triggerType_enum)newMode; } -void isoDriver::frameActionGeneric(char CH1_mode, char CH2_mode) //0 for off, 1 for ana, 2 for dig, -1 for ana750 +void isoDriver::frameActionGeneric(char CH1_mode, char CH2_mode) //0 for off, 1 for ana, 2 for dig, -1 for ana750, -2 for file { //qDebug() << "made it to frameActionGeneric"; if(!paused_CH1 && CH1_mode == - 1){ @@ -702,7 +720,7 @@ void isoDriver::frameActionGeneric(char CH1_mode, char CH2_mode) //0 for off, 1 readData375_CH1 = internalBuffer375_CH1->readBuffer(window,GRAPH_SAMPLES,CH1_mode==2, delay + ((triggerEnabled&&!paused_CH1) ? triggerDelay + window/2 : 0)); if(CH2_mode) readData375_CH2 = internalBuffer375_CH2->readBuffer(window,GRAPH_SAMPLES,CH2_mode==2, delay + (triggerEnabled ? triggerDelay + window/2 : 0)); if(CH1_mode == -1) readData750 = internalBuffer750->readBuffer(window,GRAPH_SAMPLES,false, delay + (triggerEnabled ? triggerDelay + window/2 : 0)); - + if(CH1_mode == -2) readDataFile = internalBufferFile->readBuffer(window,GRAPH_SAMPLES,false, delay); //qDebug() << "Trigger Delay =" << triggerDelay; @@ -732,6 +750,11 @@ void isoDriver::frameActionGeneric(char CH1_mode, char CH2_mode) //0 for off, 1 broadcastStats(0); } + if(CH1_mode == -2) { + fileStreamConvert(readDataFile, &CH1); + } + + for (double i=0; i0) { @@ -1301,6 +1324,7 @@ void isoDriver::loadFileBuffer(QFile *fileToLoad){ } qDebug("There are %d elements!", numel); + //Prompt user for start and end times double defaultSampleRate = 375000; if(mode == 6){ @@ -1313,8 +1337,61 @@ void isoDriver::loadFileBuffer(QFile *fileToLoad){ daqLoadPrompt dlp(this, minTime, maxTime); connect(&dlp, SIGNAL(startTime(double)), this, SLOT(daqLoad_startChanged(double))); connect(&dlp, SIGNAL(endTime(double)), this, SLOT(daqLoad_endChanged(double))); + + //Defaults + daqLoad_startTime = minTime; + daqLoad_endTime = maxTime; + dlp.exec(); - //Copy the data into the isoBuffer + + //Initialise the (modified) isoBuffer. + int bufferLen = (int)(((daqLoad_endTime - daqLoad_startTime)/minTime) * 1.1) + 1; //Add a bit on to account for rounding error. Int conversion rounds down, so we add 1. + qDebug() << "daqLoad_endTime" << daqLoad_endTime; + qDebug() << "daqLoad_startTime" << daqLoad_startTime; + qDebug() << "minTime" << minTime; + qDebug() << "bufferLen" << bufferLen; + double sampleRate_Hz = defaultSampleRate/averages; + internalBufferFile = new isoBuffer_file(this, bufferLen, sampleRate_Hz); + + //Go to start of data section + fileToLoad->seek(0);//Return to start + currentLine = fileToLoad->readLine(); //Chew up header + qDebug() << currentLine; + currentLine = fileToLoad->readLine(); //Chew up averages line + qDebug() << currentLine; + currentLine = fileToLoad->readLine(); //Chew up mode line + qDebug() << currentLine; + tempList.clear(); + + //Copy the data into the (modified) isoBuffer + float tempArray[COLUMN_BREAK + 1]; //751 elements per row with the old files; this just avoids a possible crash; + int temp_len; + + qDebug() << "Loading data into isoBuffer_file"; + while (!fileToLoad->atEnd()) { + currentLine = fileToLoad->readLine(); + tempList.append(currentLine.split(',')); + tempList.removeLast(); //Last element is a "\n", not a number. + temp_len = tempList.count(); + for (int i=0; iwriteBuffer_float(tempArray, temp_len); + tempList.clear(); + } + + qDebug() << "Initialising timer"; + //Initialise the file timer. + if (fileTimer != NULL){ + delete fileTimer; + } + fileTimer = new QTimer(); + fileTimer->setTimerType(Qt::PreciseTimer); + fileTimer->start(TIMER_PERIOD); + connect(fileTimer, SIGNAL(timeout()), this, SLOT(fileTimerTick())); + qDebug() << "File Buffer loaded!"; + enableFileMode(); + qDebug() << "File Mode Enabled"; } void isoDriver::daqLoad_startChanged(double newStart){ @@ -1327,5 +1404,19 @@ void isoDriver::daqLoad_endChanged(double newEnd){ daqLoad_endTime = newEnd; } +void isoDriver::fileTimerTick(){ + //qDebug() << "isoDriver::fileTimerTick()"; + frameActionGeneric(-2,0); +} + +void isoDriver::enableFileMode(){ + fileModeEnabled = true; + daq_maxWindowSize = daqLoad_endTime - daqLoad_startTime; +} + +void isoDriver::disableFileMode(){ + fileModeEnabled = false; +} + diff --git a/Desktop_Interface/isodriver.h b/Desktop_Interface/isodriver.h index 6c6b19b8..03a9a81c 100644 --- a/Desktop_Interface/isodriver.h +++ b/Desktop_Interface/isodriver.h @@ -11,6 +11,7 @@ #include "siprint.h" class isoBuffer; +class isoBuffer_file; //isoDriver is a huge class. It handles everything related to the isochronous IN stream - and perhaps that constraint was applied a bit too loosely (spot the C programmer...). //Too much stuff is handled in this class, and it's too heavily entangled with the (generic/win/unix)UsbDriver classes. @@ -22,7 +23,8 @@ class isoDriver : public QLabel public: explicit isoDriver(QWidget *parent = 0); //Generic Vars - isoBuffer *internalBuffer375_CH1, *internalBuffer375_CH2, *internalBuffer750, *internalBufferFile = NULL; + isoBuffer *internalBuffer375_CH1, *internalBuffer375_CH2, *internalBuffer750; + isoBuffer_file *internalBufferFile = NULL; #if QCP_VER == 1 QCPItemText *cursorTextPtr; #endif @@ -44,6 +46,9 @@ public: void setAxes(QCustomPlot *newAxes); double meanVoltageLast(double seconds, unsigned char channel, int TOP); void loadFileBuffer(QFile *fileToLoad); + //DAQ + bool fileModeEnabled = false; + double daq_maxWindowSize; private: //Those bloody bools that just Enable/Disable a single property bool paused_CH1 = false, paused_CH2 = false, paused_multimeter = false; @@ -75,6 +80,7 @@ private: //Generic Functions void analogConvert(short *shortPtr, QVector *doublePtr, int TOP, bool AC, int channel); void digitalConvert(short *shortPtr, QVector *doublePtr); + void fileStreamConvert(float *floatPtr, QVector *doublePtr); bool properlyPaused(); void autoGain(void); void udateCursors(void); @@ -86,6 +92,7 @@ private: //Variables that are just pointers to other classes/vars QCustomPlot *axes; short *readData375_CH1, *readData375_CH2, *readData750; + float *readDataFile; char *isoTemp = NULL; short *isoTemp_short = NULL; siprint *v0, *v1, *dv, *t0, *t1, *dt, *f; @@ -106,11 +113,12 @@ private: double seriesResistance = 0; //Generic Vars double windowAtPause = 0.01; - QTimer* isoTimer = NULL, *slowTimer = NULL; + QTimer* isoTimer = NULL, *slowTimer = NULL, *fileTimer = NULL; long total_read = 0; unsigned int length; QFile *snapshotFile_CH1; QFile *snapshotFile_CH2; + //DAQ double daqLoad_startTime, daqLoad_endTime; signals: @@ -193,6 +201,9 @@ public slots: void serialNeedsDisabling(int channel); void daqLoad_startChanged(double newStart); void daqLoad_endChanged(double newEnd); + void fileTimerTick(); + void enableFileMode(); + void disableFileMode(); }; #endif // ISODRIVER_H diff --git a/Desktop_Interface/mainwindow.cpp b/Desktop_Interface/mainwindow.cpp index 05e4b716..04ac8c6c 100644 --- a/Desktop_Interface/mainwindow.cpp +++ b/Desktop_Interface/mainwindow.cpp @@ -966,8 +966,9 @@ void MainWindow::cycleDelayRight(){ void MainWindow::cycleDelayLeft(){ qDebug() << "LEFT"; + double mws = ui->controller_iso->fileModeEnabled ? ui->controller_iso->daq_maxWindowSize : ((double)MAX_WINDOW_SIZE); ui->controller_iso->delay += ui->controller_iso->window/10; - if(ui->controller_iso->delay > (MAX_WINDOW_SIZE - ui->controller_iso->window)) ui->controller_iso->delay = (MAX_WINDOW_SIZE - ui->controller_iso->window); + if(ui->controller_iso->delay > (mws - ui->controller_iso->window)) ui->controller_iso->delay = (mws - ui->controller_iso->window); } void MainWindow::cycleDelayRight_large(){ @@ -978,8 +979,9 @@ void MainWindow::cycleDelayRight_large(){ void MainWindow::cycleDelayLeft_large(){ qDebug() << "LEFT"; + double mws = ui->controller_iso->fileModeEnabled ? ui->controller_iso->daq_maxWindowSize : ((double)MAX_WINDOW_SIZE); ui->controller_iso->delay += ui->controller_iso->window/2; - if(ui->controller_iso->delay > (MAX_WINDOW_SIZE - ui->controller_iso->window)) ui->controller_iso->delay = (MAX_WINDOW_SIZE - ui->controller_iso->window); + if(ui->controller_iso->delay > (mws - ui->controller_iso->window)) ui->controller_iso->delay = (mws - ui->controller_iso->window); } void MainWindow::enableLabradorDebugging(){ diff --git a/Desktop_Interface/ui_files_desktop/daqloadprompt.ui b/Desktop_Interface/ui_files_desktop/daqloadprompt.ui index 5b8f541f..1a2aa527 100644 --- a/Desktop_Interface/ui_files_desktop/daqloadprompt.ui +++ b/Desktop_Interface/ui_files_desktop/daqloadprompt.ui @@ -50,6 +50,27 @@ + + + + + + Contiguous RAM required: + + + + + + + TextLabel + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + +