Labrador/Desktop_Interface/isobuffer.cpp

393 lines
12 KiB
C++
Raw Normal View History

#include "isobuffer.h"
#include "isodriver.h"
#include "uartstyledecoder.h"
isoBuffer::isoBuffer(QWidget *parent, int bufferLen, isoDriver *caller, unsigned char channel_value) : QWidget(parent)
{
buffer = (short *) calloc(bufferLen*2, sizeof(short));
bufferEnd = bufferLen-1;
samplesPerSecond = (double) bufferLen/(double)21;
samplesPerSecond = samplesPerSecond/375*VALID_DATA_PER_375;
sampleRate_bit = samplesPerSecond * 8;
virtualParent = caller;
channel = channel_value;
}
void isoBuffer::openFile(QString newFile)
{
if (fptr != NULL){
fclose(fptr);
}
if (newFile.isEmpty()){
fptr = NULL;
}
else {
QByteArray temp = newFile.toLatin1();
char *fileName = temp.data();
fptr = fopen(fileName, "w");
if (fptr == NULL) qFatal("Null fptr in isoBuffer::openFile");
qDebug() << "opening file" << fileName;
qDebug() << "fptr = " << fptr;
}
}
void isoBuffer::writeBuffer_char(char* data, int len)
{
double convertedSample;
for (int i=0; i<len;i++){
//qDebug() << "i = " << i;
buffer[back] = (short) data[i];
if (back == bufferEnd){
back = 0;
firstTime = false;
}
else back++;
//Output to CSV
if(fileIOEnabled){
2017-12-27 01:44:49 +00:00
//Current sample
convertedSample = sampleConvert(data[i], 128, channel==1 ? virtualParent->AC_CH1 : virtualParent->AC_CH2);
//Accumulate
average_sample_temp += convertedSample;
fileIO_sampleCount++;
//Check to see if we can write a new sample to file
if(fileIO_sampleCount == fileIO_maxIncrementedSampleValue){
char numStr[32];
2017-12-27 01:44:49 +00:00
sprintf(numStr,"%7.5f, ", average_sample_temp/((double)fileIO_maxIncrementedSampleValue));
currentFile->write(numStr);
currentColumn++;
2017-12-27 23:17:32 +00:00
if (currentColumn >= COLUMN_BREAK){
currentFile->write("\n");
currentColumn = 0;
}
2017-12-27 01:44:49 +00:00
//Reset the average and sample count for next data point
fileIO_sampleCount = 0;
2017-12-27 01:44:49 +00:00
average_sample_temp = 0;
//Check to see if we've reached the max file size.
if(fileIO_max_file_size != 0){ //value of 0 means "no limit"
fileIO_numBytesWritten += 9; //7 chars for the number, 1 for the comma and 1 for the space = 9 bytes per sample.
if(fileIO_numBytesWritten >= fileIO_max_file_size){
fileIOEnabled = false; //Just in case signalling fails.
fileIOinternalDisable();
}
}
}
}
}
return;
}
void isoBuffer::writeBuffer_short(short* data, int len)
{
//for (int i=(len-1);i>-1;i--){
for (int i=0; i<len;i++){
//qDebug() << "i = " << i;
buffer[back] = (short) data[i] >> 4; //Because it's a left adjust value!
if (back == bufferEnd){
back = 0;
firstTime = false;
}
else back++;
2017-12-27 03:38:16 +00:00
double convertedSample;
//Output to CSV
if(fileIOEnabled){
//Current sample
convertedSample = sampleConvert((data[i] >> 4), 2048, channel==1 ? virtualParent->AC_CH1 : virtualParent->AC_CH2);
//Accumulate
average_sample_temp += convertedSample;
fileIO_sampleCount++;
//Check to see if we can write a new sample to file
if(fileIO_sampleCount == fileIO_maxIncrementedSampleValue){
char numStr[32];
sprintf(numStr,"%7.5f, ", average_sample_temp/((double)fileIO_maxIncrementedSampleValue));
currentFile->write(numStr);
currentColumn++;
2017-12-27 23:17:32 +00:00
if (currentColumn >= COLUMN_BREAK){
2017-12-27 03:38:16 +00:00
currentFile->write("\n");
currentColumn = 0;
}
//Reset the average and sample count for next data point
fileIO_sampleCount = 0;
average_sample_temp = 0;
//Check to see if we've reached the max file size.
if(fileIO_max_file_size != 0){ //value of 0 means "no limit"
fileIO_numBytesWritten += 9; //7 chars for the number, 1 for the comma and 1 for the space = 9 bytes per sample.
if(fileIO_numBytesWritten >= fileIO_max_file_size){
fileIOEnabled = false; //Just in case signalling fails.
fileIOinternalDisable();
}
}
}
}
}
return;
}
short *isoBuffer::readBuffer(double sampleWindow, int numSamples, bool singleBit, double delayOffset)
{
//ignore singleBit for now
double timeBetweenSamples = (double) sampleWindow * (double) samplesPerSecond / (double) numSamples;
double accumulatedDelay = 0;
int delaySamples = (int)((double)delayOffset * (double)samplesPerSecond);
int front = back - 1 - delaySamples;
if (front < 0) front = 0;
int idx, subIdx;
if(readData!=NULL) free(readData);
readData = (short *) calloc(numSamples, sizeof(short));
if(singleBit){
for (int i=0; i<numSamples;i++){
if (timeBetweenSamples > (double) front){
accumulatedDelay -= (double) front;
front = bufferEnd;
}
idx = (int) floor(((double) front - accumulatedDelay));
subIdx = (int) floor(8*(((double) front - accumulatedDelay) - floor(((double) front - accumulatedDelay))));
//qDebug() << "subIdx = " << subIdx;
if (idx < 0){
accumulatedDelay--;
accumulatedDelay -= (double) front;
front = bufferEnd;
idx = (int) round(((double) front - accumulatedDelay));
}
2018-11-04 00:31:48 +00:00
readData[i] = buffer[idx] & (1 << subIdx);
accumulatedDelay += timeBetweenSamples;
}
}else{
for (int i=0; i<numSamples;i++){
if (timeBetweenSamples > (double) front){
accumulatedDelay -= (double) front;
front = bufferEnd;
}
idx = (int) round(((double) front - accumulatedDelay));
if (idx < 0){
accumulatedDelay--;
accumulatedDelay -= (double) front;
front = bufferEnd;
idx = (int) round(((double) front - accumulatedDelay));
}
readData[i] = buffer[idx];
accumulatedDelay += timeBetweenSamples;
}
}
return readData;
}
void isoBuffer::clearBuffer()
{
for (int i=0; i<bufferEnd;i++){
buffer[i] = 0;
}
back = 0;
firstTime = true;
}
void isoBuffer::gainBuffer(int gain_log)
{
qDebug() << "Buffer shifted by" << gain_log;
for (int i=0; i<bufferEnd; i++){
if (gain_log == -1) buffer[i] *= 2;
else buffer[i] /= 2;
}
}
void isoBuffer::glitchInsert(short type)
{
}
2017-12-27 01:44:49 +00:00
void isoBuffer::enableFileIO(QFile *file, int samplesToAverage, qulonglong max_file_size){
//Open the file
file->open(QIODevice::WriteOnly);
currentFile = file;
2017-12-27 01:44:49 +00:00
//Add the header
char headerLine[256];
2017-12-27 03:39:56 +00:00
sprintf(headerLine, "EspoTek Labrador DAQ V1.0 Output File\nAveraging = %d\nMode = %d\n", samplesToAverage, virtualParent->driver->deviceMode);
2017-12-27 01:44:49 +00:00
currentFile->write(headerLine);
//Set up the isoBuffer for DAQ
fileIO_maxIncrementedSampleValue = samplesToAverage;
fileIO_max_file_size = max_file_size;
fileIO_sampleCount = 0;
fileIO_numBytesWritten = 0;
2017-12-27 01:44:49 +00:00
average_sample_temp = 0;
//Enable DAQ
fileIOEnabled = true;
2017-12-27 01:44:49 +00:00
qDebug("File IO enabled, averaging %d samples, max file size %uMB", samplesToAverage, max_file_size/1000000);
qDebug() << max_file_size;
return;
}
void isoBuffer::disableFileIO(){
fileIOEnabled = false;
currentColumn = 0;
currentFile->close();
return;
}
double isoBuffer::sampleConvert(short sample, int TOP, bool AC){
double scope_gain = (double)(virtualParent->driver->scopeGain);
double voltageLevel;
voltageLevel = (sample * (vcc/2)) / (frontendGain*scope_gain*TOP);
if (virtualParent->driver->deviceMode != 7) voltageLevel += voltage_ref;
#ifdef INVERT_MM
if(virtualParent->driver->deviceMode == 7) voltageLevel *= -1;
#endif
if(AC){
voltageLevel -= virtualParent->currentVmean; //This is old (1 frame in past) value and might not be good for signals with large variations in DC level (although the cap should filter that anyway)??
}
return voltageLevel;
}
short isoBuffer::inverseSampleConvert(double voltageLevel, int TOP, bool AC){
double scope_gain = (double)(virtualParent->driver->scopeGain);
short sample;
if(AC){
voltageLevel += virtualParent->currentVmean; //This is old (1 frame in past) value and might not be good for signals with large variations in DC level (although the cap should filter that anyway)??
}
#ifdef INVERT_MM
if(virtualParent->driver->deviceMode == 7) voltageLevel *= -1;
#endif
if (virtualParent->driver->deviceMode != 7) voltageLevel -= voltage_ref;
//voltageLevel = (sample * (vcc/2)) / (frontendGain*scope_gain*TOP);
sample = (voltageLevel * (frontendGain*scope_gain*TOP))/(vcc/2);
return sample;
}
#define NUM_SAMPLES_SEEKING_CAP (20)
#ifdef INVERT_MM
#define X0_COMPARISON_CAP >
#define X1_X2_COMPARISON_CAP <
#else
#define X0_COMPARISON_CAP <
#define X1_X2_COMPARISON_CAP >
#endif
2017-12-28 02:23:33 +00:00
//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){
return -1; //too hard, not really important
}
short vbot_s = inverseSampleConvert(vbot, 2048, 0);
qDebug() << "vbot_s (x0) = " << vbot_s;
int num_found = 0;
for(int i=samplesInPast; i; i--){
short currentSample = buffer[back - i];
if(currentSample X0_COMPARISON_CAP vbot_s){
num_found++;
} else num_found--;
if(num_found < 0){
num_found = 0;
}
if (num_found > NUM_SAMPLES_SEEKING_CAP){
return samplesInPast-i;
}
}
return -1;
}
int isoBuffer::cap_x1fromLast(double seconds, int x0, double vbot){
int samplesInPast = seconds * samplesPerSecond;
samplesInPast -= x0;
if(back < samplesInPast){
return -1; //too hard, not really important
}
short vbot_s = inverseSampleConvert(vbot, 2048, 0);
qDebug() << "vbot_s (x1) = " << vbot_s;
int num_found = 0;
for(int i=samplesInPast; i; i--){
short currentSample = buffer[back - i];
if(currentSample X1_X2_COMPARISON_CAP vbot_s){
num_found++;
} else num_found--;
if(num_found < 0){
num_found = 0;
}
if (num_found > NUM_SAMPLES_SEEKING_CAP){
return samplesInPast-i + x0;
}
}
return -1;
}
int isoBuffer::cap_x2fromLast(double seconds, int x1, double vtop){
int samplesInPast = seconds * samplesPerSecond;
samplesInPast -= x1;
if(back < samplesInPast){
return -1; //too hard, not really important
}
short vtop_s = inverseSampleConvert(vtop, 2048, 0);
qDebug() << "vtop_s (x2) = " << vtop_s;
int num_found = 0;
for(int i=samplesInPast; i; i--){
short currentSample = buffer[back - i];
if(currentSample X1_X2_COMPARISON_CAP vtop_s){
num_found++;
} else num_found--;
if(num_found < 0){
num_found = 0;
}
if (num_found > NUM_SAMPLES_SEEKING_CAP){
return samplesInPast-i + x1;
}
}
return -1;
}
void isoBuffer::serialManage(double baudRate, int type){
//Types:
// 0 - standard UART, no parity
// 1 - standard UART, with parity bit
// 100 - I2C
if(decoder == NULL){
decoder = new uartStyleDecoder(this);
connect(decoder, SIGNAL(wireDisconnected(int)), virtualParent, SLOT(serialNeedsDisabling(int)));
}
if(stopDecoding){
decoder->updateTimer->start(CONSOLE_UPDATE_TIMER_PERIOD);
stopDecoding = false;
}
decoder->serialDecode(baudRate);
}