Isobuffer refactor (#64)

* make isobuffer.cpp follow the common bracket style

* Add a few utility functions to isoBuffer, and reorganize and comment isobuffer.h

* refactor a few functions in isoBuffer using the newly added functions

* Clean up isoBuffer::readBuffer. Requires particular attention during review

* remove unused variable isoBuffer::firstTime

* Fix formatting and add a comment to isoBuffer::maybeOutputSampleToFile

* move invariant out of loop in isoBuffer::writeBuffer_short

* Substantially refactor isoBuffer::readBuffer

* change spaces to tabs on isoBuffer.h

* spaces to tabs on isobuffer.cpp and isobuffer.h, but properly

* Enforce const correctness on some methods of isoBuffer

* Add some comments to isobuffer.cpp

* Remove duplication in isoBuffer::cap_xnfromxxx functions by extracting common functionality to a free function

* Format isobuffer.h and isobuffer.cpp

* add inserted count to isoBuffer

* further modification to isoBuffer::readBuffer

* Correct a comment in isoBuffer::readBuffer

* add an anonymous namespace with file-wide constants

* remove isoBuffer::openFile, and move initialization isoBuffer to initializer list

* add lines between if statements in isoBuffer::insertIntoBuffer

* add spaces after // to some comments

* extract common functionality from writeBuffer_xxx functions to function template

* update header file to reflect previous commits

* make isoBuffer::return nullptr in a troublesome case

* add space after // to some other comments

* Make capSample a member function of isoBuffer, delete a macro in isobuffer.cpp

* clean up various comments and declarations in isobuffer.cpp

* make isoBuffer::gainBuffer work for any gain value

* make enableFileIO use the constant definitions made in a recent commit

* Remove type argument from isoBuffer::serialManage

* make isoBuffer::readBuffer return a zero-filled buffer instead of null

* Remove isoBuffer::glitchInsert

* Add a bunch of TODOs to isobuffer.cpp and isobuffer.h

* Rename member variables of isoBuffer to have an m_ prefix

* Move isoBuffer::capSample comparison functors to anonymous namespace

* Make CONSOLE_UPDATE_TIMER_PERIOD on isobuffer.h a constexpr intead of a macro
This commit is contained in:
Sebastián Mestre 2019-01-23 02:13:40 -03:00 committed by Chris Esposito
parent 4499db10bf
commit 015d41624d
6 changed files with 429 additions and 438 deletions

View File

@ -20,14 +20,14 @@ void i2cDecoder::reset()
{ {
qDebug () << "Resetting I2C"; qDebug () << "Resetting I2C";
if (sda->back != scl->back) if (sda->m_back != scl->m_back)
{ {
// Perhaps the data could be saved, but just resetting them seems much safer // Perhaps the data could be saved, but just resetting them seems much safer
sda->clearBuffer(); sda->clearBuffer();
scl->clearBuffer(); scl->clearBuffer();
} }
serialPtr_bit = sda->back * 8; serialPtr_bit = sda->m_back * 8;
{ {
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
@ -40,20 +40,20 @@ void i2cDecoder::reset()
void i2cDecoder::run() void i2cDecoder::run()
{ {
// qDebug() << "i2cDecoder::run()"; // qDebug() << "i2cDecoder::run()";
while (serialDistance(sda) > SERIAL_DELAY * sda->sampleRate_bit) while (serialDistance(sda) > SERIAL_DELAY * sda->m_sampleRate_bit)
{ {
updateBitValues(); updateBitValues();
runStateMachine(); runStateMachine();
serialPtr_bit ++; serialPtr_bit ++;
if (serialPtr_bit > (sda->bufferEnd * 8)) if (serialPtr_bit > (sda->m_bufferEnd * 8))
serialPtr_bit -= (sda->bufferEnd * 8); serialPtr_bit -= (sda->m_bufferEnd * 8);
} }
} }
int i2cDecoder::serialDistance(isoBuffer* buffer) int i2cDecoder::serialDistance(isoBuffer* buffer)
{ {
int back_bit = buffer->back * 8; int back_bit = buffer->m_back * 8;
int bufferEnd_bit = buffer->bufferEnd * 8; int bufferEnd_bit = buffer->m_bufferEnd * 8;
if (back_bit >= serialPtr_bit) if (back_bit >= serialPtr_bit)
return back_bit - serialPtr_bit; return back_bit - serialPtr_bit;
else else
@ -66,8 +66,8 @@ void i2cDecoder::updateBitValues(){
int coord_byte = serialPtr_bit/8; int coord_byte = serialPtr_bit/8;
int coord_bit = serialPtr_bit - (8*coord_byte); int coord_bit = serialPtr_bit - (8*coord_byte);
unsigned char dataByteSda = sda->buffer[coord_byte]; unsigned char dataByteSda = sda->m_buffer[coord_byte];
unsigned char dataByteScl = scl->buffer[coord_byte]; unsigned char dataByteScl = scl->m_buffer[coord_byte];
unsigned char mask = (0x01 << coord_bit); unsigned char mask = (0x01 << coord_bit);
currentSdaValue = dataByteSda & mask; currentSdaValue = dataByteSda & mask;
currentSclValue = dataByteScl & mask; currentSclValue = dataByteScl & mask;
@ -91,7 +91,7 @@ void i2cDecoder::runStateMachine()
state = transmissionState::unknown; state = transmissionState::unknown;
qDebug() << "Dumping I2C state and aborting..."; qDebug() << "Dumping I2C state and aborting...";
for (int i=31; i>=0; i--) for (int i=31; i>=0; i--)
qDebug("%02x\t%02x", sda->buffer[serialPtr_bit/8 - i] & 0xFF, scl->buffer[serialPtr_bit/8 - i] & 0xFF); qDebug("%02x\t%02x", sda->m_buffer[serialPtr_bit/8 - i] & 0xFF, scl->m_buffer[serialPtr_bit/8 - i] & 0xFF);
throw std::runtime_error("unknown i2c transmission state"); throw std::runtime_error("unknown i2c transmission state");
return; return;
} }
@ -217,7 +217,7 @@ void i2cDecoder::updateConsole(){
return; return;
console->setPlainText(QString::fromLocal8Bit(serialBuffer->begin(), serialBuffer->size())); console->setPlainText(QString::fromLocal8Bit(serialBuffer->begin(), serialBuffer->size()));
if(sda->serialAutoScroll){ if(sda->m_serialAutoScroll){
QTextCursor c = console->textCursor(); QTextCursor c = console->textCursor();
c.movePosition(QTextCursor::End); c.movePosition(QTextCursor::End);
console->setTextCursor(c); console->setTextCursor(c);

View File

@ -2,391 +2,343 @@
#include "isodriver.h" #include "isodriver.h"
#include "uartstyledecoder.h" #include "uartstyledecoder.h"
isoBuffer::isoBuffer(QWidget *parent, int bufferLen, isoDriver *caller, unsigned char channel_value) : QWidget(parent) namespace {
{ static char const * fileHeaderFormat =
buffer = (short *) calloc(bufferLen*2, sizeof(short)); "EspoTek Labrador DAQ V1.0 Output File\n"
bufferEnd = bufferLen-1; "Averaging = %d\n"
samplesPerSecond = (double) bufferLen/(double)21; "Mode = %d\n";
samplesPerSecond = samplesPerSecond/375*VALID_DATA_PER_375;
sampleRate_bit = samplesPerSecond * 8; constexpr auto kSamplesSeekingCap = 20;
virtualParent = caller;
channel = channel_value; #ifdef INVERT_MM
constexpr auto fX0Comp = std::greater<int> {};
constexpr auto fX1X2Comp = std::less<int> {};
#else
constexpr auto fX0Comp = std::less<int> {};
constexpr auto fX1X2Comp = std::greater<int> {};
#endif
constexpr auto kTopMultimeter = 2048;
} }
void isoBuffer::openFile(QString newFile)
isoBuffer::isoBuffer(QWidget* parent, int bufferLen, isoDriver* caller, unsigned char channel_value)
: QWidget(parent)
, m_buffer((short*)calloc(bufferLen*2, sizeof(short)))
, m_bufferEnd(bufferLen-1)
, m_samplesPerSecond(bufferLen/21.0/375*VALID_DATA_PER_375)
, m_sampleRate_bit(bufferLen/21.0/375*VALID_DATA_PER_375*8)
, m_virtualParent(caller)
, m_channel(channel_value)
{ {
if (fptr != NULL){ }
fclose(fptr);
void isoBuffer::insertIntoBuffer(short item)
{
m_buffer[m_back] = item;
m_back++;
m_insertedCount++;
if (m_insertedCount > m_bufferEnd)
{
m_insertedCount = m_bufferEnd+1;
} }
if (newFile.isEmpty()){
fptr = NULL; if (m_back > m_bufferEnd)
{
m_back = 0;
}
}
short isoBuffer::bufferAt(int idx) const
{
return m_buffer[m_back - idx];
}
bool isoBuffer::maybeOutputSampleToFile(double convertedSample)
{
/*
* This function adds a sample to an accumulator and bumps the sample count.
* After the sample count hits some threshold, the accumulated sample is
* outputted to a file. If this 'saturates' the file, then fileIO is disabled.
*/
m_average_sample_temp += convertedSample;
m_fileIO_sampleCount++;
// Check to see if we can write a new sample to file
if (m_fileIO_sampleCount == m_fileIO_maxIncrementedSampleValue)
{
char numStr[32];
sprintf(numStr,"%7.5f, ", m_average_sample_temp/((double)m_fileIO_maxIncrementedSampleValue));
m_currentFile->write(numStr);
m_currentColumn++;
if (m_currentColumn >= COLUMN_BREAK)
{
m_currentFile->write("\n");
m_currentColumn = 0;
}
// Reset the average and sample count for next data point
m_fileIO_sampleCount = 0;
m_average_sample_temp = 0;
// Check to see if we've reached the max file size.
if (m_fileIO_max_file_size != 0) // value of 0 means "no limit"
{
m_fileIO_numBytesWritten += 9; // 7 chars for the number, 1 for the comma and 1 for the space = 9 bytes per sample.
if (m_fileIO_numBytesWritten >= m_fileIO_max_file_size)
{
m_fileIOEnabled = false; // Just in case signalling fails.
fileIOinternalDisable();
return false;
}
}
}
return true;
}
template<typename T, typename Function>
void isoBuffer::writeBuffer(T* data, int len, int TOP, Function transform)
{
for (int i = 0; i < len; ++i)
{
insertIntoBuffer(transform(data[i]));
}
// Output to CSV
if (m_fileIOEnabled)
{
bool isUsingAC = m_channel == 1
? m_virtualParent->AC_CH1
: m_virtualParent->AC_CH2;
for (int i = 0; i < len; i++)
{
double convertedSample = sampleConvert(data[i], TOP, isUsingAC);
bool keepOutputting = maybeOutputSampleToFile(convertedSample);
if (!keepOutputting) break;
} }
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) void isoBuffer::writeBuffer_char(char* data, int len)
{ {
double convertedSample; writeBuffer(data, len, 128, [](char item) -> short {return item;});
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){
//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];
sprintf(numStr,"%7.5f, ", average_sample_temp/((double)fileIO_maxIncrementedSampleValue));
currentFile->write(numStr);
currentColumn++;
if (currentColumn >= COLUMN_BREAK){
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;
} }
void isoBuffer::writeBuffer_short(short* data, int len) void isoBuffer::writeBuffer_short(short* data, int len)
{ {
//for (int i=(len-1);i>-1;i--){ writeBuffer(data, len, 2048, [](short item) -> short {return item >> 4;});
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++;
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++;
if (currentColumn >= COLUMN_BREAK){
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)
short *isoBuffer::readBuffer(double sampleWindow, int numSamples, bool singleBit, double delayOffset)
{ {
//ignore singleBit for now /* Refactor Note:
double timeBetweenSamples = (double) sampleWindow * (double) samplesPerSecond / (double) numSamples; *
double accumulatedDelay = 0; * Refactoring this function took a few passes were i made some assumptions:
int delaySamples = (int)((double)delayOffset * (double)samplesPerSecond); * - round() should be replaced by floor() where it was used
* - int(floor(x)) and int(x) are equivalent (since we are always positive)
* - free(NULL) is a no-op. This is mandated by the C standard, and virtually all
* implementations comply. A few known exceptions are:
* - PalmOS
* - 3BSD
* - UNIX 7
* I do not know of any non-compliant somewhat modern implementations.
*
* The expected behavior is to cycle backwards over the buffer, taking into
* acount only the part of the buffer that has things stored, with a stride
* of timeBetweenSamples steps, and insert the touched elements into readData.
*
* ~Sebastian Mestre
*/
const double timeBetweenSamples = sampleWindow * m_samplesPerSecond / numSamples;
const int delaySamples = delayOffset * m_samplesPerSecond;
int front = back - 1 - delaySamples; free(m_readData);
if (front < 0) front = 0;
int idx, subIdx;
if(readData!=NULL) free(readData);
readData = (short *) calloc(numSamples, sizeof(short));
if(singleBit){ m_readData = (short*) calloc(numSamples, sizeof(short));
for (int i=0; i<numSamples;i++){
if (timeBetweenSamples > (double) front){ // TODO: replace by return nullptr and add error handling upstream
accumulatedDelay -= (double) front; if(delaySamples+1 > m_insertedCount)
front = bufferEnd; {
return m_readData;
} }
idx = (int) floor(((double) front - accumulatedDelay)); double itr = delaySamples + 1;
subIdx = (int) floor(8*(((double) front - accumulatedDelay) - floor(((double) front - accumulatedDelay)))); for (int i = 0; i < numSamples; i++)
{
while (itr > m_insertedCount)
itr -= m_insertedCount;
//qDebug() << "subIdx = " << subIdx; m_readData[i] = bufferAt(int(itr));
if (idx < 0){ if (singleBit)
accumulatedDelay--; {
accumulatedDelay -= (double) front; int subIdx = 8*(-itr-floor(-itr));
front = bufferEnd; m_readData[i] &= (1 << subIdx);
idx = (int) round(((double) front - accumulatedDelay));
}
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)); itr += timeBetweenSamples;
if (idx < 0){
accumulatedDelay--;
accumulatedDelay -= (double) front;
front = bufferEnd;
idx = (int) round(((double) front - accumulatedDelay));
}
readData[i] = buffer[idx];
accumulatedDelay += timeBetweenSamples;
}
} }
return readData; return m_readData;
} }
void isoBuffer::clearBuffer() void isoBuffer::clearBuffer()
{ {
for (int i=0; i<bufferEnd;i++){ for (int i = 0; i < m_bufferEnd; i++)
buffer[i] = 0; {
m_buffer[i] = 0;
} }
back = 0; m_back = 0;
firstTime = true;
} }
void isoBuffer::gainBuffer(int gain_log) void isoBuffer::gainBuffer(int gain_log)
{ {
qDebug() << "Buffer shifted by" << gain_log; qDebug() << "Buffer shifted by" << gain_log;
for (int i=0; i<bufferEnd; i++){ for (int i = 0; i < m_bufferEnd; i++)
if (gain_log == -1) buffer[i] *= 2; {
else buffer[i] /= 2; if (gain_log < 0)
m_buffer[i] <<= -gain_log;
else
m_buffer[i] >>= gain_log;
} }
} }
void isoBuffer::enableFileIO(QFile* file, int samplesToAverage, qulonglong max_file_size)
void isoBuffer::glitchInsert(short type)
{ {
} // Open the file
void isoBuffer::enableFileIO(QFile *file, int samplesToAverage, qulonglong max_file_size){
//Open the file
file->open(QIODevice::WriteOnly); file->open(QIODevice::WriteOnly);
currentFile = file; m_currentFile = file;
//Add the header // Add the header
char headerLine[256]; char headerLine[256];
sprintf(headerLine, "EspoTek Labrador DAQ V1.0 Output File\nAveraging = %d\nMode = %d\n", samplesToAverage, virtualParent->driver->deviceMode); sprintf(headerLine, fileHeaderFormat, samplesToAverage, m_virtualParent->driver->deviceMode);
currentFile->write(headerLine); m_currentFile->write(headerLine);
//Set up the isoBuffer for DAQ // Set up the isoBuffer for DAQ
fileIO_maxIncrementedSampleValue = samplesToAverage; m_fileIO_maxIncrementedSampleValue = samplesToAverage;
fileIO_max_file_size = max_file_size; m_fileIO_max_file_size = max_file_size;
fileIO_sampleCount = 0; m_fileIO_sampleCount = 0;
fileIO_numBytesWritten = 0; m_fileIO_numBytesWritten = 0;
average_sample_temp = 0; m_average_sample_temp = 0;
//Enable DAQ // Enable DAQ
fileIOEnabled = true; m_fileIOEnabled = true;
qDebug("File IO enabled, averaging %d samples, max file size %uMB", samplesToAverage, max_file_size/1000000); qDebug("File IO enabled, averaging %d samples, max file size %lluMB", samplesToAverage, max_file_size/1000000);
qDebug() << max_file_size; qDebug() << max_file_size;
return; return;
} }
void isoBuffer::disableFileIO(){ void isoBuffer::disableFileIO()
fileIOEnabled = false; {
currentColumn = 0; m_fileIOEnabled = false;
currentFile->close(); m_currentColumn = 0;
m_currentFile->close();
return; return;
} }
double isoBuffer::sampleConvert(short sample, int TOP, bool AC){ double isoBuffer::sampleConvert(short sample, int TOP, bool AC) const
{
double scope_gain = (double)(m_virtualParent->driver->scopeGain);
double scope_gain = (double)(virtualParent->driver->scopeGain); double voltageLevel = (sample * (vcc/2)) / (m_frontendGain*scope_gain*TOP);
double voltageLevel; if (m_virtualParent->driver->deviceMode != 7) voltageLevel += m_voltage_ref;
#ifdef INVERT_MM
if (m_virtualParent->driver->deviceMode == 7) voltageLevel *= -1;
#endif
voltageLevel = (sample * (vcc/2)) / (frontendGain*scope_gain*TOP); if (AC)
if (virtualParent->driver->deviceMode != 7) voltageLevel += voltage_ref; {
#ifdef INVERT_MM // This is old (1 frame in past) value and might not be good for signals with
if(virtualParent->driver->deviceMode == 7) voltageLevel *= -1; // large variations in DC level (although the cap should filter that anyway)??
#endif voltageLevel -= m_virtualParent->currentVmean;
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; return voltageLevel;
} }
short isoBuffer::inverseSampleConvert(double voltageLevel, int TOP, bool AC) const
{
double scope_gain = m_virtualParent->driver->scopeGain;
if (AC)
short isoBuffer::inverseSampleConvert(double voltageLevel, int TOP, bool AC){ {
// This is old (1 frame in past) value and might not be good for signals with
double scope_gain = (double)(virtualParent->driver->scopeGain); // large variations in DC level (although the cap should filter that anyway)??
short sample; voltageLevel += m_virtualParent->currentVmean;
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); #ifdef INVERT_MM
sample = (voltageLevel * (frontendGain*scope_gain*TOP))/(vcc/2); if (m_virtualParent->driver->deviceMode == 7) voltageLevel *= -1;
#endif
if (m_virtualParent->driver->deviceMode != 7) voltageLevel -= m_voltage_ref;
// voltageLevel = (sample * (vcc/2)) / (frontendGain*scope_gain*TOP);
short sample = (voltageLevel * (m_frontendGain*scope_gain*TOP))/(vcc/2);
return sample; return sample;
} }
#define NUM_SAMPLES_SEEKING_CAP (20) template<typename Function>
int isoBuffer::capSample(int offset, int target, double seconds, double value, Function comp)
{
int samples = seconds * m_samplesPerSecond;
#ifdef INVERT_MM if (m_back < samples + offset) return -1;
#define X0_COMPARISON_CAP >
#define X1_X2_COMPARISON_CAP <
#else
#define X0_COMPARISON_CAP <
#define X1_X2_COMPARISON_CAP >
#endif
//For capacitance measurement. x0, x1 and x2 are all various time points used to find the RC coefficient. short sample = inverseSampleConvert(value, 2048, 0);
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; int found = 0;
for(int i=samplesInPast; i; i--){ for (int i = samples + offset; i--;)
short currentSample = buffer[back - i]; {
if(currentSample X0_COMPARISON_CAP vbot_s){ short currentSample = bufferAt(i);
num_found++; if (comp(currentSample, sample))
} else num_found--; found = found + 1;
if(num_found < 0){ else
num_found = 0; found = std::max(0, found-1);
}
if (num_found > NUM_SAMPLES_SEEKING_CAP){ if (found > target)
return samplesInPast-i; return samples - i;
}
} }
return -1; return -1;
} }
int isoBuffer::cap_x1fromLast(double seconds, int x0, double vbot){ // For capacitance measurement. x0, x1 and x2 are all various time points used to find the RC coefficient.
int samplesInPast = seconds * samplesPerSecond; int isoBuffer::cap_x0fromLast(double seconds, double vbot)
samplesInPast -= x0; {
if(back < samplesInPast){ return capSample(0, kSamplesSeekingCap, seconds, vbot, fX0Comp);
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 isoBuffer::cap_x1fromLast(double seconds, int x0, double vbot)
int samplesInPast = seconds * samplesPerSecond; {
samplesInPast -= x1; return capSample(-x0, kSamplesSeekingCap, seconds, vbot, fX1X2Comp);
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, UartParity parity){ int isoBuffer::cap_x2fromLast(double seconds, int x1, double vtop)
//Types: {
// 0 - standard UART, no parity return capSample(-x1, kSamplesSeekingCap, seconds, vtop, fX1X2Comp);
// 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->setParityMode(parity);
decoder->serialDecode(baudRate);
} }
void isoBuffer::serialManage(double baudRate, UartParity parity)
{
if (m_decoder == NULL)
{
m_decoder = new uartStyleDecoder(this);
// TODO: Look into using the type safe version of connect.
// NOTE: I believe Qt has a type-safe version of this, without the macros and the
// explicit signature and stuff, i think it uses member-function pointers instead.
connect(m_decoder, SIGNAL(wireDisconnected(int)), m_virtualParent, SLOT(serialNeedsDisabling(int)));
}
if (m_stopDecoding)
{
m_decoder->updateTimer->start(CONSOLE_UPDATE_TIMER_PERIOD);
m_stopDecoding = false;
}
m_decoder->setParityMode(parity);
m_decoder->serialDecode(baudRate);
}

View File

@ -1,6 +1,8 @@
#ifndef ISOBUFFER_H #ifndef ISOBUFFER_H
#define ISOBUFFER_H #define ISOBUFFER_H
// TODO: Make object macros constexprs or globals
// TODO: Move headers used only in implementation to isobuffer.cpp
#include <QWidget> #include <QWidget>
#include <QString> #include <QString>
#include <QByteArray> #include <QByteArray>
@ -18,61 +20,98 @@ class isoDriver;
class uartStyleDecoder; class uartStyleDecoder;
enum class UartParity : uint8_t; enum class UartParity : uint8_t;
//isoBuffer is a generic class that enables O(1) read times (!!!) on all read/write operations, while maintaining a huge buffer size. // isoBuffer is a generic class that enables O(1) read times (!!!) on all
//Imagine it as a circular buffer, but with access functions specifically designed for isochronous data from an Xmega. // read/write operations, while maintaining a huge buffer size.
// Imagine it as a circular buffer, but with access functions specifically
// designed for isochronous data from an Xmega.
#define CONSOLE_UPDATE_TIMER_PERIOD (ISO_PACKETS_PER_CTX * 4) constexpr auto CONSOLE_UPDATE_TIMER_PERIOD = ISO_PACKETS_PER_CTX * 4;
// TODO: Make private what should be private
// TODO: Add m_ prefix to member variables
// TODO: Change integer types to cstdint types
class isoBuffer : public QWidget class isoBuffer : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
isoBuffer(QWidget *parent = 0, int bufferLen = 0, isoDriver *caller = 0, unsigned char channel_value = 0); // TODO: Add consoles as constructor arguments
//Generic Functions isoBuffer(QWidget* parent = 0, int bufferLen = 0, isoDriver* caller = 0, unsigned char channel_value = 0);
void openFile(QString newFile); // TODO?: Add a destructor
void writeBuffer_char(char *data, int len);
void writeBuffer_short(short *data, int len); // Basic buffer operations
short *readBuffer(double sampleWindow, int numSamples, bool singleBit, double delayOffset); short bufferAt(int idx) const;
void insertIntoBuffer(short item);
void clearBuffer(); void clearBuffer();
void gainBuffer(int gain_log); void gainBuffer(int gain_log);
void glitchInsert(short type);
double sampleConvert(short sample, int TOP, bool AC); // Advanced buffer operations
short inverseSampleConvert(double voltageLevel, int TOP, bool AC); private:
template<typename T, typename Function>
void writeBuffer(T* data, int len, int TOP, Function transform);
public:
void writeBuffer_char(char* data, int len);
void writeBuffer_short(short* data, int len);
// TODO: Change return value to unique_ptr
short* readBuffer(double sampleWindow, int numSamples, bool singleBit, double delayOffset);
// file I/O
bool maybeOutputSampleToFile(double convertedSample);
double sampleConvert(short sample, int TOP, bool AC) const;
short inverseSampleConvert(double voltageLevel, int TOP, bool AC) const;
private:
template<typename Function>
int capSample(int offset, int target, double seconds, double value, Function comp);
public:
int cap_x0fromLast(double seconds, double vbot); int cap_x0fromLast(double seconds, double vbot);
int cap_x1fromLast(double seconds, int x0, double vbot); int cap_x1fromLast(double seconds, int x0, double vbot);
int cap_x2fromLast(double seconds, int x1, double vtop); int cap_x2fromLast(double seconds, int x1, double vtop);
void serialManage(double baudRate, int type, UartParity parity); void serialManage(double baudRate, UartParity parity);
//Generic Vars
QPlainTextEdit *console1, *console2; // ---- MEMBER VARIABLES ----
bool serialAutoScroll = true;
unsigned char channel = 255; // Presentantion?
double voltage_ref = 1.65; // NOTE: it seems like these are never initialized but they are used as though they were...
double frontendGain = (R4 / (R3 + R4)); QPlainTextEdit* m_console1;
int samplesPerSecond; QPlainTextEdit* m_console2;
int sampleRate_bit; unsigned char m_channel = 255;
int bufferEnd, back = 0; bool m_serialAutoScroll = true;
short *buffer, *readData = NULL;
uartStyleDecoder *decoder = NULL; // Conversion And Sampling
bool stopDecoding = false; double m_voltage_ref = 1.65;
double m_frontendGain = (R4 / (R3 + R4));
int m_samplesPerSecond;
int m_sampleRate_bit;
// Internal Storage
int m_back = 0;
int m_insertedCount = 0;
int m_bufferEnd;
// TODO: Change buffer to be a unique_ptr
short* m_buffer;
short* m_readData = NULL;
// UARTS decoding
uartStyleDecoder* m_decoder = NULL;
// TODO: change this to keepDecoding
bool m_stopDecoding = false;
private: private:
//Generic Vars // File I/O
bool firstTime = true; bool m_fileIOEnabled = false;
//File I/O FILE* m_fptr = NULL;
bool fileIOEnabled = false; QFile* m_currentFile;
FILE* fptr = NULL; int m_fileIO_maxIncrementedSampleValue;
QFile *currentFile; int m_fileIO_sampleCount;
int fileIO_maxIncrementedSampleValue; qulonglong m_fileIO_max_file_size;
int fileIO_sampleCount; qulonglong m_fileIO_numBytesWritten;
qulonglong fileIO_max_file_size; unsigned int m_currentColumn = 0;
qulonglong fileIO_numBytesWritten; isoDriver* m_virtualParent;
//isoDriver *parent; double m_average_sample_temp;
unsigned int currentColumn = 0;
isoDriver *virtualParent;
double average_sample_temp;
signals: signals:
void fileIOinternalDisable(); void fileIOinternalDisable();
public slots: public slots:
void enableFileIO(QFile *file, int samplesToAverage, qulonglong max_file_size); void enableFileIO(QFile* file, int samplesToAverage, qulonglong max_file_size);
void disableFileIO(); void disableFileIO();
}; };

View File

@ -90,10 +90,10 @@ void isoDriver::timerTick(void){
if (deviceMode_prev != 1) if (deviceMode_prev != 1)
clearBuffers(false, true, false); clearBuffers(false, true, false);
internalBuffer375_CH2->channel = 1; internalBuffer375_CH2->m_channel = 1;
frameActionGeneric(1,2); frameActionGeneric(1,2);
if(serialDecodeEnabled_CH1 && serialType == 0){ if(serialDecodeEnabled_CH1 && serialType == 0){
internalBuffer375_CH2->serialManage(baudRate_CH1, 0, parity_CH1); internalBuffer375_CH2->serialManage(baudRate_CH1, parity_CH1);
} }
break; break;
case 2: case 2:
@ -110,7 +110,7 @@ void isoDriver::timerTick(void){
frameActionGeneric(2,0); frameActionGeneric(2,0);
if(serialDecodeEnabled_CH1 && serialType == 0){ if(serialDecodeEnabled_CH1 && serialType == 0){
internalBuffer375_CH1->serialManage(baudRate_CH1, 0, parity_CH1); internalBuffer375_CH1->serialManage(baudRate_CH1, parity_CH1);
} }
break; break;
case 4: case 4:
@ -119,13 +119,13 @@ void isoDriver::timerTick(void){
if (deviceMode_prev != 4) if (deviceMode_prev != 4)
clearBuffers(false, true, false); clearBuffers(false, true, false);
internalBuffer375_CH2->channel = 2; internalBuffer375_CH2->m_channel = 2;
frameActionGeneric(2,2); frameActionGeneric(2,2);
if(serialDecodeEnabled_CH1 && serialType == 0){ if(serialDecodeEnabled_CH1 && serialType == 0){
internalBuffer375_CH1->serialManage(baudRate_CH1, 0, parity_CH1); internalBuffer375_CH1->serialManage(baudRate_CH1, parity_CH1);
} }
if(serialDecodeEnabled_CH2 && serialType == 0){ if(serialDecodeEnabled_CH2 && serialType == 0){
internalBuffer375_CH2->serialManage(baudRate_CH2, 0, parity_CH2); internalBuffer375_CH2->serialManage(baudRate_CH2, parity_CH2);
} }
if (serialDecodeEnabled_CH1 && serialType == 1) if (serialDecodeEnabled_CH1 && serialType == 1)
{ {
@ -1169,7 +1169,7 @@ void isoDriver::multimeterStats(){
qDebug() << "x2 = " << cap_x2; qDebug() << "x2 = " << cap_x2;
qDebug() << "dt = " << cap_x2-cap_x1; qDebug() << "dt = " << cap_x2-cap_x1;
double dt = (double)(cap_x2-cap_x1)/internalBuffer375_CH1->samplesPerSecond; double dt = (double)(cap_x2-cap_x1)/internalBuffer375_CH1->m_samplesPerSecond;
double Cm = -dt/(seriesResistance * log((vcc-cap_vtop)/(vcc-cap_vbot))); double Cm = -dt/(seriesResistance * log((vcc-cap_vtop)/(vcc-cap_vbot)));
qDebug() << "Cm = " << Cm; qDebug() << "Cm = " << Cm;
@ -1555,7 +1555,7 @@ void isoDriver::setSerialType(unsigned char type)
{ {
if (twoWire) if (twoWire)
delete twoWire; delete twoWire;
twoWire = new i2c::i2cDecoder(internalBuffer375_CH1, internalBuffer375_CH2, internalBuffer375_CH1->console1); twoWire = new i2c::i2cDecoder(internalBuffer375_CH1, internalBuffer375_CH2, internalBuffer375_CH1->m_console1);
} }
} }

View File

@ -41,11 +41,11 @@ MainWindow::MainWindow(QWidget *parent) :
ui->voltageInfoRmsDisplay_CH1->display(6.00); ui->voltageInfoRmsDisplay_CH1->display(6.00);
connectDisplaySignals(); connectDisplaySignals();
ui->controller_iso->internalBuffer375_CH1->console1 = ui->console1; ui->controller_iso->internalBuffer375_CH1->m_console1 = ui->console1;
ui->controller_iso->internalBuffer375_CH1->console2 = ui->console2; ui->controller_iso->internalBuffer375_CH1->m_console2 = ui->console2;
ui->controller_iso->internalBuffer375_CH2->console1 = ui->console1; ui->controller_iso->internalBuffer375_CH2->m_console1 = ui->console1;
ui->controller_iso->internalBuffer375_CH2->console2 = ui->console2; ui->controller_iso->internalBuffer375_CH2->m_console2 = ui->console2;
initShortcuts(); initShortcuts();
ui->debugButton1->setVisible(0); ui->debugButton1->setVisible(0);
@ -1204,12 +1204,12 @@ void MainWindow::readSettingsFile(){
ui->controller_iso->ch2_ref = 3.3 - calibrate_vref_ch2; ui->controller_iso->ch2_ref = 3.3 - calibrate_vref_ch2;
ui->controller_iso->frontendGain_CH1 = calibrate_gain_ch1; ui->controller_iso->frontendGain_CH1 = calibrate_gain_ch1;
ui->controller_iso->frontendGain_CH2 = calibrate_gain_ch2; ui->controller_iso->frontendGain_CH2 = calibrate_gain_ch2;
ui->controller_iso->internalBuffer375_CH1->voltage_ref = 3.3 - calibrate_vref_ch1; ui->controller_iso->internalBuffer375_CH1->m_voltage_ref = 3.3 - calibrate_vref_ch1;
ui->controller_iso->internalBuffer750->voltage_ref = 3.3 - calibrate_vref_ch1; ui->controller_iso->internalBuffer750->m_voltage_ref = 3.3 - calibrate_vref_ch1;
ui->controller_iso->internalBuffer375_CH2->voltage_ref = 3.3 - calibrate_vref_ch2; ui->controller_iso->internalBuffer375_CH2->m_voltage_ref = 3.3 - calibrate_vref_ch2;
ui->controller_iso->internalBuffer375_CH1->frontendGain = calibrate_gain_ch1; ui->controller_iso->internalBuffer375_CH1->m_frontendGain = calibrate_gain_ch1;
ui->controller_iso->internalBuffer750->frontendGain = calibrate_gain_ch1; ui->controller_iso->internalBuffer750->m_frontendGain = calibrate_gain_ch1;
ui->controller_iso->internalBuffer375_CH2->frontendGain = calibrate_gain_ch2; ui->controller_iso->internalBuffer375_CH2->m_frontendGain = calibrate_gain_ch2;
if(!dt_AlreadyAskedAboutCalibration && ((calibrate_vref_ch1 == 1.65) || (calibrate_vref_ch2 == 1.65) || (calibrate_gain_ch1 == R4/(R3+R4)) || (calibrate_gain_ch2 == R4/(R3+R4)))){ if(!dt_AlreadyAskedAboutCalibration && ((calibrate_vref_ch1 == 1.65) || (calibrate_vref_ch2 == 1.65) || (calibrate_gain_ch1 == R4/(R3+R4)) || (calibrate_gain_ch2 == R4/(R3+R4)))){
//Prompt user to calibrate if no calibration data found. //Prompt user to calibrate if no calibration data found.
@ -1698,12 +1698,12 @@ void MainWindow::on_actionCalibrate_triggered()
ui->controller_iso->ch2_ref = 1.65; ui->controller_iso->ch2_ref = 1.65;
ui->controller_iso->frontendGain_CH1 = (R4/(R3+R4)); ui->controller_iso->frontendGain_CH1 = (R4/(R3+R4));
ui->controller_iso->frontendGain_CH2 = (R4/(R3+R4)); ui->controller_iso->frontendGain_CH2 = (R4/(R3+R4));
ui->controller_iso->internalBuffer375_CH1->voltage_ref = 1.65; ui->controller_iso->internalBuffer375_CH1->m_voltage_ref = 1.65;
ui->controller_iso->internalBuffer750->voltage_ref = 1.65; ui->controller_iso->internalBuffer750->m_voltage_ref = 1.65;
ui->controller_iso->internalBuffer375_CH2->voltage_ref = 1.65; ui->controller_iso->internalBuffer375_CH2->m_voltage_ref = 1.65;
ui->controller_iso->internalBuffer375_CH1->frontendGain = R4/(R3+R4); ui->controller_iso->internalBuffer375_CH1->m_frontendGain = R4/(R3+R4);
ui->controller_iso->internalBuffer750->frontendGain = R4/(R3+R4); ui->controller_iso->internalBuffer750->m_frontendGain = R4/(R3+R4);
ui->controller_iso->internalBuffer375_CH2->frontendGain = R4/(R3+R4); ui->controller_iso->internalBuffer375_CH2->m_frontendGain = R4/(R3+R4);
settings->setValue("CalibrateVrefCH1", 1.65); settings->setValue("CalibrateVrefCH1", 1.65);
settings->setValue("CalibrateVrefCH2", 1.65); settings->setValue("CalibrateVrefCH2", 1.65);
@ -1733,9 +1733,9 @@ void MainWindow::calibrateStage2(){
ui->controller_iso->ch1_ref = 3.3 - vref_CH1; ui->controller_iso->ch1_ref = 3.3 - vref_CH1;
ui->controller_iso->ch2_ref = 3.3 - vref_CH2; ui->controller_iso->ch2_ref = 3.3 - vref_CH2;
ui->controller_iso->internalBuffer375_CH1->voltage_ref = 3.3 - vref_CH1; ui->controller_iso->internalBuffer375_CH1->m_voltage_ref = 3.3 - vref_CH1;
ui->controller_iso->internalBuffer750->voltage_ref = 3.3 - vref_CH1; ui->controller_iso->internalBuffer750->m_voltage_ref = 3.3 - vref_CH1;
ui->controller_iso->internalBuffer375_CH2->voltage_ref = 3.3 - vref_CH2; ui->controller_iso->internalBuffer375_CH2->m_voltage_ref = 3.3 - vref_CH2;
settings->setValue("CalibrateVrefCH1", vref_CH1); settings->setValue("CalibrateVrefCH1", vref_CH1);
settings->setValue("CalibrateVrefCH2", vref_CH2); settings->setValue("CalibrateVrefCH2", vref_CH2);
@ -1769,9 +1769,9 @@ void MainWindow::calibrateStage3(){
ui->controller_iso->frontendGain_CH2 = (vref_CH2 - vMeasured_CH2)*(ui->controller_iso->frontendGain_CH2)/vref_CH2; ui->controller_iso->frontendGain_CH2 = (vref_CH2 - vMeasured_CH2)*(ui->controller_iso->frontendGain_CH2)/vref_CH2;
qDebug() << "New gain (CH1) = " << ui->controller_iso->frontendGain_CH1; qDebug() << "New gain (CH1) = " << ui->controller_iso->frontendGain_CH1;
ui->controller_iso->internalBuffer375_CH1->frontendGain = (vref_CH1 - vMeasured_CH1)*(ui->controller_iso->frontendGain_CH1)/vref_CH1; ui->controller_iso->internalBuffer375_CH1->m_frontendGain = (vref_CH1 - vMeasured_CH1)*(ui->controller_iso->frontendGain_CH1)/vref_CH1;
ui->controller_iso->internalBuffer750->frontendGain = (vref_CH1 - vMeasured_CH1)*(ui->controller_iso->frontendGain_CH1)/vref_CH1; ui->controller_iso->internalBuffer750->m_frontendGain = (vref_CH1 - vMeasured_CH1)*(ui->controller_iso->frontendGain_CH1)/vref_CH1;
ui->controller_iso->internalBuffer375_CH2->frontendGain = (vref_CH2 - vMeasured_CH2)*(ui->controller_iso->frontendGain_CH2)/vref_CH2; ui->controller_iso->internalBuffer375_CH2->m_frontendGain = (vref_CH2 - vMeasured_CH2)*(ui->controller_iso->frontendGain_CH2)/vref_CH2;
settings->setValue("CalibrateGainCH1", ui->controller_iso->frontendGain_CH1); settings->setValue("CalibrateGainCH1", ui->controller_iso->frontendGain_CH1);
settings->setValue("CalibrateGainCH2", ui->controller_iso->frontendGain_CH2); settings->setValue("CalibrateGainCH2", ui->controller_iso->frontendGain_CH2);
calibrationMessages->setText("Oscilloscope Calibration complete."); calibrationMessages->setText("Oscilloscope Calibration complete.");

View File

@ -7,7 +7,7 @@ uartStyleDecoder::uartStyleDecoder(QObject *parent_in) : QObject(parent_in)
parent = (isoBuffer *) parent_in; parent = (isoBuffer *) parent_in;
// Begin decoding SAMPLE_DELAY seconds in the past. // Begin decoding SAMPLE_DELAY seconds in the past.
serialPtr_bit = (int)(parent->back * 8 - SERIAL_DELAY * parent->sampleRate_bit + parent->bufferEnd * 8) % (parent->bufferEnd*8); serialPtr_bit = (int)(parent->m_back * 8 - SERIAL_DELAY * parent->m_sampleRate_bit + parent->m_bufferEnd * 8) % (parent->m_bufferEnd*8);
updateTimer = new QTimer(); updateTimer = new QTimer();
updateTimer->setTimerType(Qt::PreciseTimer); updateTimer->setTimerType(Qt::PreciseTimer);
@ -16,8 +16,8 @@ uartStyleDecoder::uartStyleDecoder(QObject *parent_in) : QObject(parent_in)
serialBuffer = new isoBufferBuffer(SERIAL_BUFFER_LENGTH); serialBuffer = new isoBufferBuffer(SERIAL_BUFFER_LENGTH);
if(parent->channel == 1) console = parent->console1; if(parent->m_channel == 1) console = parent->m_console1;
else if(parent->channel == 2) console = parent->console2; else if(parent->m_channel == 2) console = parent->m_console2;
else qFatal("Nonexistant console requested in uartStyleDecoder::serialDecode"); else qFatal("Nonexistant console requested in uartStyleDecoder::serialDecode");
} }
@ -34,7 +34,7 @@ void uartStyleDecoder::updateConsole(){
//qDebug() << serialBuffer->size(); //qDebug() << serialBuffer->size();
console->setPlainText(QString::fromLocal8Bit(serialBuffer->begin(), serialBuffer->size())); console->setPlainText(QString::fromLocal8Bit(serialBuffer->begin(), serialBuffer->size()));
if(parent->serialAutoScroll){ if(parent->m_serialAutoScroll){
//http://stackoverflow.com/questions/21059678/how-can-i-set-auto-scroll-for-a-qtgui-qtextedit-in-pyqt4 DANKON //http://stackoverflow.com/questions/21059678/how-can-i-set-auto-scroll-for-a-qtgui-qtextedit-in-pyqt4 DANKON
QTextCursor c = console->textCursor(); QTextCursor c = console->textCursor();
c.movePosition(QTextCursor::End); c.movePosition(QTextCursor::End);
@ -50,7 +50,7 @@ void uartStyleDecoder::serialDecode(double baudRate)
/*if(stopDecoding){ /*if(stopDecoding){
return; return;
}*/ }*/
double dist_seconds = (double)serialDistance()/(parent->sampleRate_bit); double dist_seconds = (double)serialDistance()/(parent->m_sampleRate_bit);
double bitPeriod_seconds = 1/baudRate; double bitPeriod_seconds = 1/baudRate;
// Used to check for wire disconnects. You should get at least one "1" for a stop bit. // Used to check for wire disconnects. You should get at least one "1" for a stop bit.
@ -76,22 +76,22 @@ void uartStyleDecoder::serialDecode(double baudRate)
// Update the pointer, accounting for jitter // Update the pointer, accounting for jitter
updateSerialPtr(baudRate, uart_bit); updateSerialPtr(baudRate, uart_bit);
// Calculate stopping condition // Calculate stopping condition
dist_seconds = (double)serialDistance()/(parent->sampleRate_bit); dist_seconds = (double)serialDistance()/(parent->m_sampleRate_bit);
} }
//Not a single stop bit, or idle bit, in the whole stream. Wire must be disconnected. //Not a single stop bit, or idle bit, in the whole stream. Wire must be disconnected.
if(allZeroes){ if(allZeroes){
qDebug() << "Wire Disconnect detected!"; qDebug() << "Wire Disconnect detected!";
wireDisconnected(parent->channel); wireDisconnected(parent->m_channel);
parent->stopDecoding = true; parent->m_stopDecoding = true;
updateTimer->stop(); updateTimer->stop();
} }
} }
int uartStyleDecoder::serialDistance() int uartStyleDecoder::serialDistance()
{ {
int back_bit = parent->back * 8; int back_bit = parent->m_back * 8;
int bufferEnd_bit = parent->bufferEnd * 8; int bufferEnd_bit = parent->m_bufferEnd * 8;
if(back_bit >= serialPtr_bit){ if(back_bit >= serialPtr_bit){
return back_bit - serialPtr_bit; return back_bit - serialPtr_bit;
}else return bufferEnd_bit - serialPtr_bit + back_bit; }else return bufferEnd_bit - serialPtr_bit + back_bit;
@ -103,20 +103,20 @@ void uartStyleDecoder::updateSerialPtr(double baudRate, unsigned char current_bi
jitterCompensationNeeded = jitterCompensationProcedure(baudRate, current_bit); jitterCompensationNeeded = jitterCompensationProcedure(baudRate, current_bit);
} }
int distance_between_bits = (parent->sampleRate_bit)/baudRate; int distance_between_bits = (parent->m_sampleRate_bit)/baudRate;
if(uartTransmitting){ if(uartTransmitting){
serialPtr_bit += distance_between_bits; serialPtr_bit += distance_between_bits;
} else serialPtr_bit += (distance_between_bits - 1); //Less than one baud period so that it will always see that start bit. } else serialPtr_bit += (distance_between_bits - 1); //Less than one baud period so that it will always see that start bit.
if (serialPtr_bit > (parent->bufferEnd * 8)){ if (serialPtr_bit > (parent->m_bufferEnd * 8)){
serialPtr_bit -= (parent->bufferEnd * 8); serialPtr_bit -= (parent->m_bufferEnd * 8);
} }
} }
unsigned char uartStyleDecoder::getNextUartBit(){ unsigned char uartStyleDecoder::getNextUartBit(){
int coord_byte = serialPtr_bit/8; int coord_byte = serialPtr_bit/8;
int coord_bit = serialPtr_bit - (8*coord_byte); int coord_bit = serialPtr_bit - (8*coord_byte);
unsigned char dataByte = parent->buffer[coord_byte]; unsigned char dataByte = parent->m_buffer[coord_byte];
unsigned char mask = (0x01 << coord_bit); unsigned char mask = (0x01 << coord_bit);
return ((dataByte & mask) ? 1 : 0); return ((dataByte & mask) ? 1 : 0);
} }
@ -155,14 +155,14 @@ bool uartStyleDecoder::jitterCompensationProcedure(double baudRate, unsigned cha
//Can't be bothered dealing with the corner case where the serial pointer is at the very start of the buffer. //Can't be bothered dealing with the corner case where the serial pointer is at the very start of the buffer.
//Just return and try again next time. //Just return and try again next time.
int left_coord = serialPtr_bit - (parent->sampleRate_bit)/baudRate; int left_coord = serialPtr_bit - (parent->m_sampleRate_bit)/baudRate;
//qDebug() << "left_coord =" << left_coord; //qDebug() << "left_coord =" << left_coord;
if (left_coord < 0){ if (left_coord < 0){
return true; //Don't want to read out of bounds!! return true; //Don't want to read out of bounds!!
} }
//The usual case, when transmitting anyway. //The usual case, when transmitting anyway.
unsigned char left_byte = (parent->buffer[left_coord/8] & 0xff); unsigned char left_byte = (parent->m_buffer[left_coord/8] & 0xff);
//Only run when a zero is detected in the leftmost symbol. //Only run when a zero is detected in the leftmost symbol.
if(left_byte != 255){ if(left_byte != 255){
//Step back, one sample at a time, to the 0->1 transition point //Step back, one sample at a time, to the 0->1 transition point
@ -172,7 +172,7 @@ bool uartStyleDecoder::jitterCompensationProcedure(double baudRate, unsigned cha
serialPtr_bit--; serialPtr_bit--;
} }
//Jump the pointer forward by half a uart bit period, and return "done!". //Jump the pointer forward by half a uart bit period, and return "done!".
serialPtr_bit += (parent->sampleRate_bit/baudRate)/2; serialPtr_bit += (parent->m_sampleRate_bit/baudRate)/2;
return false; return false;
} }