Sped up serial decode dramatically

Swapped an append to a replace with an ADT designed to return fast
pointers to char[] blocks.

Worked out that the one-corrupt-sample-per-packet bug was definitely not
fixed.  I must have been looking at a 1kHz wave before.
This commit is contained in:
EspoTek 2016-12-08 08:39:22 +11:00
parent 644359d1a2
commit d3054d9707
52 changed files with 651 additions and 147 deletions

View File

@ -20,7 +20,8 @@ SOURCES += main.cpp\
isobuffer.cpp \
desktop_settings.cpp \
scoperangeenterdialog.cpp \
genericusbdriver.cpp
genericusbdriver.cpp \
isobufferbuffer.cpp
HEADERS += mainwindow.h \
functiongencontrol.h \
@ -29,7 +30,8 @@ HEADERS += mainwindow.h \
isobuffer.h \
desktop_settings.h \
scoperangeenterdialog.h \
genericusbdriver.h
genericusbdriver.h \
isobufferbuffer.h
FORMS += mainwindow.ui \
scoperangeenterdialog.ui

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.1.0, 2016-11-28T18:20:47. -->
<!-- Written by QtCreator 4.1.0, 2016-12-05T19:42:35. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -25,11 +25,14 @@ extern double SERIAL_DELAY;
#define USB_RECONNECT_PERIOD 250
#define VALID_DATA_PER_375 375
#define VALID_DATA_PER_375 374
#define VALID_DATA_PER_750 750
#define COLUMN_BREAK VALID_DATA_PER_750
//#define MAX_CONSOLE_BLOCK_COUNT 512
#define SERIAL_BUFFER_LENGTH 8192
#endif // DESKTOP_SETTINGS_H

View File

@ -2,7 +2,7 @@
#include "isodriver.h"
isoBuffer::isoBuffer(int bufferLen, isoDriver *caller, unsigned char channel_value)
isoBuffer::isoBuffer(QWidget *parent, int bufferLen, isoDriver *caller, unsigned char channel_value) : QWidget(parent)
{
buffer = (short *) calloc(bufferLen*2, sizeof(short));
bufferEnd = bufferLen-1;
@ -10,6 +10,14 @@ isoBuffer::isoBuffer(int bufferLen, isoDriver *caller, unsigned char channel_val
samplesPerSecond = samplesPerSecond/375*VALID_DATA_PER_375;
parent = caller;
channel = channel_value;
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);
}
void isoBuffer::openFile(QString newFile)
{
@ -179,7 +187,7 @@ void isoBuffer::serialDecode(double baudRate)
tempChar = tempShort & (1 << serialPhase) ? 0 : 1;
if(serialDecodingSymbol){
//if((tempShort != 0) && (tempShort!= 255)) qDebug() << "tempShort = " << tempShort;
qDebug() << numOnes(tempShort);
//qDebug() << numOnes(tempShort);
decodeSymbol(numOnes(tempShort) > 4);
}
else serialDecodingSymbol = (numOnes(tempShort) < 8);
@ -204,15 +212,11 @@ void isoBuffer::serialBegin()
void isoBuffer::decodeSymbol(unsigned char newBit) //Slow but works.
{
if(symbolCurrent == symbolMax){ //Last bit in symbol
console -> insertPlainText(QString(QChar((char)symbol)));
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
}
//charBuffer[charPos] = symbol;
if(charPos<SERIAL_BUFFER_LENGTH) charPos++;
serialBuffer->add(symbol);
symbolCurrent++;
symbolUpdated = true;
return;
}
if(symbolCurrent > symbolMax){ //Wait for stop bit. Stops over the top calculation when you get a string of zeroes...
@ -302,3 +306,19 @@ double isoBuffer::sampleConvert(short sample, int TOP, bool AC){
return voltageLevel;
}
void isoBuffer::updateConsole(){
if(!symbolUpdated) return;
qDebug() << charPos;
console -> setPlainText(QString::fromLocal8Bit(serialBuffer->get(charPos), charPos));
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
}
symbolUpdated = false;
//charPos = 0;
}

View File

@ -1,6 +1,7 @@
#ifndef ISOBUFFER_H
#define ISOBUFFER_H
#include <QWidget>
#include <QString>
#include <QByteArray>
#include <QDebug>
@ -11,16 +12,20 @@
#include "xmega.h"
#include "desktop_settings.h"
#include "isobufferbuffer.h"
class isoDriver;
//isoBuffer is a generic class that enables O(1) read times (!!!) on all 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.
class isoBuffer
#define CONSOLE_UPDATE_TIMER_PERIOD 60
class isoBuffer : public QWidget
{
Q_OBJECT
public:
isoBuffer(int bufferLen, isoDriver *caller, unsigned char channel_value);
isoBuffer(QWidget *parent = 0, int bufferLen = 0, isoDriver *caller = 0, unsigned char channel_value = 0);
//Generic Functions
void openFile(QString newFile);
void writeBuffer_char(char *data, int len);
@ -36,6 +41,7 @@ public:
QPlainTextEdit *console, *console1, *console2;
bool serialAutoScroll = true;
unsigned char channel = 255;
QTimer *updateTimer;
private:
//Generic Vars
short *buffer, *readData = NULL;
@ -50,10 +56,14 @@ private:
unsigned int currentColumn = 0;
//Serial Decode
bool serialDecodingSymbol = false;
char charBuffer[4096];
unsigned int charPos = 0;
unsigned char symbolMax = 7;
unsigned char symbolCurrent = 0;
unsigned short symbol = 0;
char serialPhase = 0;
isoBufferBuffer *serialBuffer;
bool symbolUpdated = false;
//Generic Functions
void decodeSymbol(unsigned char newBit);
void marchSerialPtr(int bitPeriod_samples);
@ -62,7 +72,7 @@ private:
public slots:
void enableFileIO(QFile *file);
void disableFileIO();
void updateConsole();
};
#endif // ISOBUFFER_H

View File

@ -0,0 +1,25 @@
#include "isobufferbuffer.h"
isoBufferBuffer::isoBufferBuffer(int length)
{
bufferLength = length;
mid = length/2;
buffer = (char *) malloc((length * 3) / 2);
}
void isoBufferBuffer::add(char newChar){
buffer[ptr] = newChar;
if(ptr<mid){
buffer[ptr+bufferLength] = newChar;
}
if (ptr >= bufferLength){
ptr = 0;
}
else ptr++;
}
char *isoBufferBuffer::get(int length){
if (length>mid) qFatal("isoBuffer::get; length requested is too high.");
if(ptr<mid) return &buffer[ptr+bufferLength - length];
else return &buffer[ptr - length];
}

View File

@ -0,0 +1,22 @@
#ifndef ISOBUFFERBUFFER_H
#define ISOBUFFERBUFFER_H
//isobufferbuffer is a buffer designed for getting the last n things added in reverse order, in O(1) time.
#include <QDebug>
#include <stdlib.h>
class isoBufferBuffer
{
public:
isoBufferBuffer(int length);
void add(char newChar);
char *get(int length);
private:
int bufferLength;
int mid;
int ptr;
char *buffer;
};
#endif // ISOBUFFERBUFFER_H

View File

@ -4,9 +4,9 @@
isoDriver::isoDriver(QWidget *parent) : QLabel(parent)
{
this->hide();
internalBuffer375_CH1 = new isoBuffer(MAX_WINDOW_SIZE*ADC_SPS/20*21, this, 1);
internalBuffer375_CH2 = new isoBuffer(MAX_WINDOW_SIZE*ADC_SPS/20*21, this, 1);
internalBuffer750 = new isoBuffer(MAX_WINDOW_SIZE*ADC_SPS/10*21, this, 1);
internalBuffer375_CH1 = new isoBuffer(this, MAX_WINDOW_SIZE*ADC_SPS/20*21, this, 1);
internalBuffer375_CH2 = new isoBuffer(this, MAX_WINDOW_SIZE*ADC_SPS/20*21, this, 1);
internalBuffer750 = new isoBuffer(this, MAX_WINDOW_SIZE*ADC_SPS/10*21, this, 1);
isoTemp = (char *) malloc(TIMER_PERIOD*ADC_SPF + 8); //8-byte header contains (unsigned long) length
@ -47,7 +47,7 @@ void isoDriver::setWindow(int newWindow){
}
void isoDriver::timerTick(void){
qDebug() << "isoDriver SEZ Tick!";
//qDebug() << "isoDriver SEZ Tick!";
if(firstFrame){
autoGain();
firstFrame = false;

View File

@ -77,6 +77,8 @@ MainWindow::MainWindow(QWidget *parent) :
connect(ui->controller_iso->driver, SIGNAL(killMe()), this, SLOT(reinitUsb()));
#endif
connect(ui->controller_iso->driver, SIGNAL(killMe()), this, SLOT(reinitUsb()));
//ui->console1->setMaximumBlockCount(MAX_CONSOLE_BLOCK_COUNT);
//ui->console2->setMaximumBlockCount(MAX_CONSOLE_BLOCK_COUNT);
}
MainWindow::~MainWindow()

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,132 @@
/****************************************************************************
** Meta object code from reading C++ file 'isobuffer.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.7.0)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
#include "../isobuffer.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qmetatype.h>
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'isobuffer.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 67
#error "This file was generated using the moc from 5.7.0. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif
QT_BEGIN_MOC_NAMESPACE
struct qt_meta_stringdata_isoBuffer_t {
QByteArrayData data[7];
char stringdata0[64];
};
#define QT_MOC_LITERAL(idx, ofs, len) \
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
qptrdiff(offsetof(qt_meta_stringdata_isoBuffer_t, stringdata0) + ofs \
- idx * sizeof(QByteArrayData)) \
)
static const qt_meta_stringdata_isoBuffer_t qt_meta_stringdata_isoBuffer = {
{
QT_MOC_LITERAL(0, 0, 9), // "isoBuffer"
QT_MOC_LITERAL(1, 10, 12), // "enableFileIO"
QT_MOC_LITERAL(2, 23, 0), // ""
QT_MOC_LITERAL(3, 24, 6), // "QFile*"
QT_MOC_LITERAL(4, 31, 4), // "file"
QT_MOC_LITERAL(5, 36, 13), // "disableFileIO"
QT_MOC_LITERAL(6, 50, 13) // "updateConsole"
},
"isoBuffer\0enableFileIO\0\0QFile*\0file\0"
"disableFileIO\0updateConsole"
};
#undef QT_MOC_LITERAL
static const uint qt_meta_data_isoBuffer[] = {
// content:
7, // revision
0, // classname
0, 0, // classinfo
3, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
// slots: name, argc, parameters, tag, flags
1, 1, 29, 2, 0x0a /* Public */,
5, 0, 32, 2, 0x0a /* Public */,
6, 0, 33, 2, 0x0a /* Public */,
// slots: parameters
QMetaType::Void, 0x80000000 | 3, 4,
QMetaType::Void,
QMetaType::Void,
0 // eod
};
void isoBuffer::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
isoBuffer *_t = static_cast<isoBuffer *>(_o);
Q_UNUSED(_t)
switch (_id) {
case 0: _t->enableFileIO((*reinterpret_cast< QFile*(*)>(_a[1]))); break;
case 1: _t->disableFileIO(); break;
case 2: _t->updateConsole(); break;
default: ;
}
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
switch (_id) {
default: *reinterpret_cast<int*>(_a[0]) = -1; break;
case 0:
switch (*reinterpret_cast<int*>(_a[1])) {
default: *reinterpret_cast<int*>(_a[0]) = -1; break;
case 0:
*reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< QFile* >(); break;
}
break;
}
}
}
const QMetaObject isoBuffer::staticMetaObject = {
{ &QWidget::staticMetaObject, qt_meta_stringdata_isoBuffer.data,
qt_meta_data_isoBuffer, qt_static_metacall, Q_NULLPTR, Q_NULLPTR}
};
const QMetaObject *isoBuffer::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}
void *isoBuffer::qt_metacast(const char *_clname)
{
if (!_clname) return Q_NULLPTR;
if (!strcmp(_clname, qt_meta_stringdata_isoBuffer.stringdata0))
return static_cast<void*>(const_cast< isoBuffer*>(this));
return QWidget::qt_metacast(_clname);
}
int isoBuffer::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QWidget::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 3)
qt_static_metacall(this, _c, _id, _a);
_id -= 3;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 3)
qt_static_metacall(this, _c, _id, _a);
_id -= 3;
}
return _id;
}
QT_END_MOC_NAMESPACE

Binary file not shown.