2016-09-07 07:36:43 +01:00
# include "isobuffer.h"
2016-09-28 01:15:18 +01:00
# include "isodriver.h"
2016-09-07 07:36:43 +01:00
2016-09-28 01:15:18 +01:00
2016-12-07 21:39:22 +00:00
isoBuffer : : isoBuffer ( QWidget * parent , int bufferLen , isoDriver * caller , unsigned char channel_value ) : QWidget ( parent )
2016-09-07 07:36:43 +01:00
{
buffer = ( short * ) calloc ( bufferLen * 2 , sizeof ( short ) ) ;
bufferEnd = bufferLen - 1 ;
samplesPerSecond = ( double ) bufferLen / ( double ) 21 ;
2016-11-27 23:38:14 +00:00
samplesPerSecond = samplesPerSecond / 375 * VALID_DATA_PER_375 ;
2017-05-28 07:34:53 +01:00
sampleRate_bit = samplesPerSecond * 8 ;
2017-02-03 06:34:54 +00:00
virtualParent = caller ;
2016-09-28 01:15:18 +01:00
channel = channel_value ;
2016-12-07 21:39:22 +00:00
updateTimer = new QTimer ( ) ;
updateTimer - > setTimerType ( Qt : : PreciseTimer ) ;
updateTimer - > start ( CONSOLE_UPDATE_TIMER_PERIOD ) ;
connect ( updateTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( updateConsole ( ) ) ) ;
serialBuffer = new isoBufferBuffer ( SERIAL_BUFFER_LENGTH * 2 ) ;
2016-09-07 07:36:43 +01:00
}
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 )
{
2016-09-28 01:15:18 +01:00
double convertedSample ;
2016-09-07 07:36:43 +01:00
for ( int i = 0 ; i < len ; i + + ) {
//qDebug() << "i = " << i;
buffer [ back ] = ( short ) data [ i ] ;
if ( back = = bufferEnd ) {
back = 0 ;
firstTime = false ;
}
else back + + ;
2016-09-26 05:17:41 +01:00
//Output to CSV
if ( fileIOEnabled ) {
2017-02-03 06:34:54 +00:00
convertedSample = sampleConvert ( data [ i ] , 128 , channel = = 1 ? virtualParent - > AC_CH1 : virtualParent - > AC_CH2 ) ;
2016-09-26 05:17:41 +01:00
char numStr [ 32 ] ;
2016-09-28 01:15:18 +01:00
sprintf ( numStr , " %f, " , convertedSample ) ;
2016-09-26 05:17:41 +01:00
currentFile - > write ( numStr ) ;
currentColumn + + ;
if ( currentColumn > COLUMN_BREAK ) {
currentFile - > write ( " \n " ) ;
currentColumn = 0 ;
}
}
2016-09-07 07:36:43 +01:00
}
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 + + ;
}
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 ) ) ) ) ;
2017-05-25 02:34:58 +01:00
//qDebug() << "subIdx = " << subIdx;
2016-09-07 07:36:43 +01:00
if ( idx < 0 ) {
accumulatedDelay - - ;
accumulatedDelay - = ( double ) front ;
front = bufferEnd ;
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 ) ) ;
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 ;
2017-05-28 07:34:53 +01:00
//serialPtr = 0;
//serialDecodingSymbol = false;
//symbolCurrent = 0;
//symbol = 0;
2016-09-07 07:36:43 +01:00
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 )
{
}
2016-09-26 05:17:41 +01:00
void isoBuffer : : enableFileIO ( QFile * file ) {
file - > open ( QIODevice : : WriteOnly ) ;
currentFile = file ;
fileIOEnabled = true ;
return ;
}
void isoBuffer : : disableFileIO ( ) {
fileIOEnabled = false ;
currentColumn = 0 ;
currentFile - > close ( ) ;
return ;
}
2016-09-28 01:15:18 +01:00
double isoBuffer : : sampleConvert ( short sample , int TOP , bool AC ) {
2017-02-03 06:34:54 +00:00
double scope_gain = ( double ) ( virtualParent - > driver - > scopeGain ) ;
2016-09-28 01:15:18 +01:00
double voltageLevel ;
2017-06-26 02:12:00 +01:00
voltageLevel = ( sample * ( vcc / 2 ) ) / ( frontendGain * scope_gain * TOP ) ;
2017-06-22 05:49:50 +01:00
if ( virtualParent - > driver - > deviceMode ! = 7 ) voltageLevel + = voltage_ref ;
2016-09-28 01:15:18 +01:00
# ifdef INVERT_MM
2017-02-03 06:34:54 +00:00
if ( virtualParent - > driver - > deviceMode = = 7 ) voltageLevel * = - 1 ;
2016-09-28 01:15:18 +01:00
# endif
if ( AC ) {
2017-02-03 06:34:54 +00:00
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)??
2016-09-28 01:15:18 +01:00
}
return voltageLevel ;
}
2016-12-07 21:39:22 +00:00
void isoBuffer : : updateConsole ( ) {
2017-05-28 08:26:16 +01:00
if ( ! newUartSymbol ) return ;
qDebug ( ) < < numCharsInBuffer ;
2016-12-07 21:39:22 +00:00
2017-05-28 08:26:16 +01:00
console - > setPlainText ( QString : : fromLocal8Bit ( serialBuffer - > get ( numCharsInBuffer ) , numCharsInBuffer ) ) ;
2016-12-07 21:39:22 +00:00
if ( serialAutoScroll ) {
//http://stackoverflow.com/questions/21059678/how-can-i-set-auto-scroll-for-a-qtgui-qtextedit-in-pyqt4 DANKON
QTextCursor c = console - > textCursor ( ) ;
c . movePosition ( QTextCursor : : End ) ;
console - > setTextCursor ( c ) ;
// txtedit.ensureCursorVisible(); // you might need this also
}
2017-05-28 08:26:16 +01:00
newUartSymbol = false ;
2016-12-07 21:39:22 +00:00
//charPos = 0;
}
2017-05-28 07:34:53 +01:00
void isoBuffer : : serialDecode ( double baudRate )
{
double dist_seconds = ( double ) serialDistance ( ) / sampleRate_bit ;
double bitPeriod_seconds = 1 / baudRate ;
2017-05-28 09:49:11 +01:00
if ( channel = = 1 ) console = console1 ;
else if ( channel = = 2 ) console = console2 ;
else qFatal ( " Nonexistant console requested in isoBuffer::serialDecode " ) ;
2017-05-28 07:34:53 +01:00
while ( dist_seconds > ( bitPeriod_seconds + SERIAL_DELAY ) ) {
2017-05-28 07:40:23 +01:00
//Read next uart bit
2017-05-28 08:26:16 +01:00
unsigned char uart_bit = getNextUartBit ( ) ;
2017-05-28 07:40:23 +01:00
//Process it
2017-05-28 08:26:16 +01:00
if ( uartTransmitting ) {
decodeNextUartBit ( uart_bit ) ;
2017-05-28 09:49:11 +01:00
//qDebug() << "uart_bit = " << uart_bit;
2017-05-28 08:26:16 +01:00
} else {
uartTransmitting = ( uart_bit = = 1 ) ? false : true ;
2017-05-28 09:54:18 +01:00
jitterCompensationNeeded = true ;
2017-05-28 09:49:11 +01:00
//if(uartTransmitting) qDebug() << "Decoding symbol!";
2017-05-28 08:26:16 +01:00
}
2017-05-28 07:40:23 +01:00
//Update the pointer, accounting for jitter
2017-05-28 09:49:11 +01:00
updateSerialPtr ( baudRate , uart_bit ) ;
2017-05-28 07:40:23 +01:00
//Calculate stopping condition
dist_seconds = ( double ) serialDistance ( ) / sampleRate_bit ;
2017-05-28 07:34:53 +01:00
}
2017-05-28 09:49:11 +01:00
//qDebug() << "\n\n\n\n\n";
2017-05-28 07:34:53 +01:00
}
int isoBuffer : : serialDistance ( )
{
int back_bit = back * 8 ;
int bufferEnd_bit = bufferEnd * 8 ;
if ( back_bit > = serialPtr_bit ) {
return back_bit - serialPtr_bit ;
} else return bufferEnd_bit - serialPtr_bit + back_bit ;
}
2017-05-28 07:40:23 +01:00
2017-05-28 09:49:11 +01:00
void isoBuffer : : updateSerialPtr ( double baudRate , unsigned char current_bit )
2017-05-28 07:40:23 +01:00
{
2017-05-28 09:49:11 +01:00
if ( jitterCompensationNeeded & & uartTransmitting ) {
jitterCompensationNeeded = jitterCompensationProcedure ( baudRate , current_bit ) ;
2017-05-28 09:54:18 +01:00
//qDebug() << "JitterCompensation Needed?" << jitterCompensationNeeded;
2017-05-28 09:49:11 +01:00
}
2017-05-28 07:40:23 +01:00
int distance_between_bits = sampleRate_bit / baudRate ;
2017-05-28 09:49:11 +01:00
if ( uartTransmitting ) {
serialPtr_bit + = distance_between_bits ;
2017-05-28 10:53:31 +01:00
} else serialPtr_bit + = ( distance_between_bits - 1 ) ; //Less than one baud period so that it will always see that start bit.
2017-05-28 09:49:11 +01:00
2017-05-28 08:26:16 +01:00
if ( serialPtr_bit > ( bufferEnd * 8 ) ) {
serialPtr_bit - = ( bufferEnd * 8 ) ;
}
}
unsigned char isoBuffer : : getNextUartBit ( ) {
int coord_byte = serialPtr_bit / 8 ;
int coord_bit = serialPtr_bit - ( 8 * coord_byte ) ;
unsigned char dataByte = buffer [ coord_byte ] ;
unsigned char mask = ( 1 < < coord_bit ) ;
return ( ( dataByte & mask ) ? 1 : 0 ) ;
}
void isoBuffer : : decodeNextUartBit ( unsigned char bitValue )
{
if ( dataBit_current = = dataBit_max ) {
if ( numCharsInBuffer < SERIAL_BUFFER_LENGTH ) numCharsInBuffer + + ;
serialBuffer - > add ( currentUartSymbol ) ;
currentUartSymbol = 0 ;
dataBit_current = 0 ;
uartTransmitting = false ;
newUartSymbol = true ;
return ;
}
//else
currentUartSymbol | = ( bitValue < < dataBit_current ) ;
dataBit_current + + ;
2017-05-28 07:40:23 +01:00
}
2017-05-28 08:26:16 +01:00
2017-05-28 09:49:11 +01:00
bool isoBuffer : : jitterCompensationProcedure ( double baudRate , unsigned char current_bit ) {
if ( current_bit ! = 0 ) {
2017-05-28 09:54:18 +01:00
//qDebug() << "Current bit not zero!!";
2017-05-28 09:49:11 +01:00
return true ;
}
int left_coord = serialPtr_bit - sampleRate_bit / baudRate ;
if ( left_coord < 0 ) {
return true ; //Don't want to read out of bounds!!
}
unsigned char left_byte = ( buffer [ left_coord / 8 ] & 0xff ) ;
2017-05-28 09:54:18 +01:00
//qDebug() << "current_bit" << current_bit;
//qDebug() << "left_byte" << left_byte;
2017-05-28 09:49:11 +01:00
if ( left_byte > 0 ) {
2017-05-28 09:54:18 +01:00
//qDebug() << "Recalibration Opportunity";
2017-05-28 09:49:11 +01:00
unsigned char temp_bit = 0 ;
2017-05-28 09:54:18 +01:00
//Go back to 1-0 transition point
2017-05-28 09:49:11 +01:00
while ( ! temp_bit ) {
temp_bit = getNextUartBit ( ) ;
serialPtr_bit - - ;
}
//Jump by half a uart bit period.
serialPtr_bit + = ( sampleRate_bit / baudRate ) / 2 ;
return false ;
}
return true ;
}
2017-06-29 01:29:38 +01:00
short isoBuffer : : inverseSampleConvert ( double voltageLevel , int TOP , bool AC ) {
2017-05-28 08:26:16 +01:00
2017-06-29 00:48:50 +01:00
double scope_gain = ( double ) ( virtualParent - > driver - > scopeGain ) ;
2017-06-29 01:29:38 +01:00
short sample ;
2017-06-29 00:48:50 +01:00
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 ;
}
2017-05-28 08:26:16 +01:00
2017-06-29 01:29:38 +01:00
# 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
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 ;
}