mirror of https://github.com/EspoTek/Labrador.git
API appears to actually store iso endpoint data
This commit is contained in:
parent
e9d84cd963
commit
36b9be5837
Binary file not shown.
|
@ -51,8 +51,10 @@ OBJECTS_DIR = ./
|
||||||
####### Files
|
####### Files
|
||||||
|
|
||||||
SOURCES = librador.cpp \
|
SOURCES = librador.cpp \
|
||||||
|
o1buffer.cpp \
|
||||||
usbcallhandler.cpp
|
usbcallhandler.cpp
|
||||||
OBJECTS = librador.o \
|
OBJECTS = librador.o \
|
||||||
|
o1buffer.o \
|
||||||
usbcallhandler.o
|
usbcallhandler.o
|
||||||
DIST = /home/esposch/Qt/5.10.0/gcc_64/mkspecs/features/spec_pre.prf \
|
DIST = /home/esposch/Qt/5.10.0/gcc_64/mkspecs/features/spec_pre.prf \
|
||||||
/home/esposch/Qt/5.10.0/gcc_64/mkspecs/common/unix.conf \
|
/home/esposch/Qt/5.10.0/gcc_64/mkspecs/common/unix.conf \
|
||||||
|
@ -239,7 +241,9 @@ DIST = /home/esposch/Qt/5.10.0/gcc_64/mkspecs/features/spec_pre.prf \
|
||||||
librador.pro librador.h \
|
librador.pro librador.h \
|
||||||
librador_global.h \
|
librador_global.h \
|
||||||
librador_internal.h \
|
librador_internal.h \
|
||||||
|
o1buffer.h \
|
||||||
usbcallhandler.h librador.cpp \
|
usbcallhandler.h librador.cpp \
|
||||||
|
o1buffer.cpp \
|
||||||
usbcallhandler.cpp
|
usbcallhandler.cpp
|
||||||
QMAKE_TARGET = rador
|
QMAKE_TARGET = rador
|
||||||
DESTDIR =
|
DESTDIR =
|
||||||
|
@ -657,8 +661,8 @@ distdir: FORCE
|
||||||
@test -d $(DISTDIR) || mkdir -p $(DISTDIR)
|
@test -d $(DISTDIR) || mkdir -p $(DISTDIR)
|
||||||
$(COPY_FILE) --parents $(DIST) $(DISTDIR)/
|
$(COPY_FILE) --parents $(DIST) $(DISTDIR)/
|
||||||
$(COPY_FILE) --parents /home/esposch/Qt/5.10.0/gcc_64/mkspecs/features/data/dummy.cpp $(DISTDIR)/
|
$(COPY_FILE) --parents /home/esposch/Qt/5.10.0/gcc_64/mkspecs/features/data/dummy.cpp $(DISTDIR)/
|
||||||
$(COPY_FILE) --parents librador.h librador_global.h librador_internal.h usbcallhandler.h $(DISTDIR)/
|
$(COPY_FILE) --parents librador.h librador_global.h librador_internal.h o1buffer.h usbcallhandler.h $(DISTDIR)/
|
||||||
$(COPY_FILE) --parents librador.cpp usbcallhandler.cpp $(DISTDIR)/
|
$(COPY_FILE) --parents librador.cpp o1buffer.cpp usbcallhandler.cpp $(DISTDIR)/
|
||||||
|
|
||||||
|
|
||||||
clean: compiler_clean
|
clean: compiler_clean
|
||||||
|
@ -737,8 +741,12 @@ librador.o: librador.cpp librador.h \
|
||||||
../../../Desktop_Interface/build_linux/libusb/libusb.h
|
../../../Desktop_Interface/build_linux/libusb/libusb.h
|
||||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o librador.o librador.cpp
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o librador.o librador.cpp
|
||||||
|
|
||||||
|
o1buffer.o: o1buffer.cpp o1buffer.h
|
||||||
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o o1buffer.o o1buffer.cpp
|
||||||
|
|
||||||
usbcallhandler.o: usbcallhandler.cpp usbcallhandler.h \
|
usbcallhandler.o: usbcallhandler.cpp usbcallhandler.h \
|
||||||
../../../Desktop_Interface/build_linux/libusb/libusb.h
|
../../../Desktop_Interface/build_linux/libusb/libusb.h \
|
||||||
|
o1buffer.h
|
||||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o usbcallhandler.o usbcallhandler.cpp
|
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o usbcallhandler.o usbcallhandler.cpp
|
||||||
|
|
||||||
####### Install
|
####### Install
|
||||||
|
|
|
@ -30,12 +30,14 @@ DEPENDPATH += ../../../Desktop_Interface
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
librador.cpp \
|
librador.cpp \
|
||||||
|
o1buffer.cpp \
|
||||||
usbcallhandler.cpp
|
usbcallhandler.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
librador.h \
|
librador.h \
|
||||||
librador_global.h \
|
librador_global.h \
|
||||||
librador_internal.h \
|
librador_internal.h \
|
||||||
|
o1buffer.h \
|
||||||
usbcallhandler.h
|
usbcallhandler.h
|
||||||
|
|
||||||
unix {
|
unix {
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
#include "o1buffer.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
//o1buffer is an object that has o(1) access times for its elements.
|
||||||
|
//At the moment it's basically an array, but I'm keeping it as an object so it can be changed to something more memory efficient later.
|
||||||
|
//See isobuffer in github.com/espotek/labrador for an example of a much more compact (RAM-wise) buffer.
|
||||||
|
o1buffer::o1buffer()
|
||||||
|
{
|
||||||
|
buffer = (int *) (malloc(sizeof(int)*NUM_SAMPLES_PER_CHANNEL));
|
||||||
|
}
|
||||||
|
|
||||||
|
o1buffer::~o1buffer(){
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void o1buffer::add(int value, int address){
|
||||||
|
//Ensure that the address is not too high.
|
||||||
|
if(address >= NUM_SAMPLES_PER_CHANNEL){
|
||||||
|
address = address % NUM_SAMPLES_PER_CHANNEL;
|
||||||
|
}
|
||||||
|
if(address<0){
|
||||||
|
fprintf(stderr, "ERROR: o1buffer::add was given a negative address\n");
|
||||||
|
}
|
||||||
|
//Assign the value
|
||||||
|
buffer[address] = value;
|
||||||
|
updateMostRecentAddress(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
int o1buffer::addVector(int *firstElement, int numElements){
|
||||||
|
int currentAddress = mostRecentAddress;
|
||||||
|
|
||||||
|
for(int i=0; i< numElements; i++){
|
||||||
|
add(firstElement[i], currentAddress);
|
||||||
|
currentAddress = (currentAddress + 1) % NUM_SAMPLES_PER_CHANNEL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int o1buffer::addVector(unsigned char *firstElement, int numElements){
|
||||||
|
int currentAddress = mostRecentAddress;
|
||||||
|
|
||||||
|
for(int i=0; i< numElements; i++){
|
||||||
|
add(firstElement[i], currentAddress);
|
||||||
|
currentAddress = (currentAddress + 1) % NUM_SAMPLES_PER_CHANNEL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int o1buffer::get(int address){
|
||||||
|
//Ensure that the address is not too high.
|
||||||
|
if(address >= NUM_SAMPLES_PER_CHANNEL){
|
||||||
|
address = address % NUM_SAMPLES_PER_CHANNEL;
|
||||||
|
}
|
||||||
|
if(address<0){
|
||||||
|
fprintf(stderr, "ERROR: o1buffer::get was given a negative address\n");
|
||||||
|
}
|
||||||
|
//Return the value
|
||||||
|
return buffer[address];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void o1buffer::updateMostRecentAddress(int newAddress){
|
||||||
|
mostRecentAddress = newAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
//This function places samples in a buffer than can be plotted on the streamingDisplay.
|
||||||
|
//A small delay, is added in case the packets arrive out of order.
|
||||||
|
std::vector<double> *o1buffer::getMany_double(int numToGet, int interval_samples, int delay_samples, int filter_mode){
|
||||||
|
//Resize the vector
|
||||||
|
convertedStream_double.resize(numToGet);
|
||||||
|
|
||||||
|
//Copy raw samples out.
|
||||||
|
int tempAddress;
|
||||||
|
for(int i=0;i<numToGet;i++){
|
||||||
|
tempAddress = mostRecentAddress - delay_samples - (interval_samples * i);
|
||||||
|
if(tempAddress < 0){
|
||||||
|
tempAddress += NUM_SAMPLES_PER_CHANNEL;
|
||||||
|
}
|
||||||
|
double *data = convertedStream_double.data();
|
||||||
|
data[i] = get_filtered_sample(tempAddress, filter_mode, interval_samples);
|
||||||
|
//convertedStream_double.replace(i, buffer[tempAddress]);
|
||||||
|
}
|
||||||
|
return &convertedStream_double;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> *o1buffer::getSinceLast(int feasible_window_begin, int feasible_window_end, int interval_samples, int filter_mode){
|
||||||
|
|
||||||
|
//Calculate what sample the feasible window begins at
|
||||||
|
//printf_debugging("o1buffer::getSinceLast()\n")
|
||||||
|
int feasible_start_point = mostRecentAddress - feasible_window_begin;
|
||||||
|
if(feasible_start_point < 0){
|
||||||
|
feasible_start_point += NUM_SAMPLES_PER_CHANNEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Work out whether or not we're starting from the feasible window or the last point
|
||||||
|
int actual_start_point;
|
||||||
|
if(distanceFromMostRecentAddress(feasible_start_point) > distanceFromMostRecentAddress(stream_index_at_last_call + interval_samples)){
|
||||||
|
actual_start_point = stream_index_at_last_call + interval_samples;
|
||||||
|
} else {
|
||||||
|
actual_start_point = feasible_start_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Work out how much we're copying
|
||||||
|
int actual_sample_distance = distanceFromMostRecentAddress(actual_start_point) - distanceFromMostRecentAddress(mostRecentAddress - feasible_window_end);
|
||||||
|
int numToGet = actual_sample_distance/interval_samples;
|
||||||
|
//printf_debugging("Fetching %d samples, starting at index %d with interval %d\n", numToGet, actual_start_point, interval_samples);
|
||||||
|
|
||||||
|
//Set up the buffer
|
||||||
|
convertedStream_double.resize(numToGet);
|
||||||
|
|
||||||
|
//Copy raw samples out.
|
||||||
|
int tempAddress = stream_index_at_last_call;
|
||||||
|
for(int i=0;i<numToGet;i++){
|
||||||
|
tempAddress = actual_start_point + (interval_samples * i);
|
||||||
|
if(tempAddress >= NUM_SAMPLES_PER_CHANNEL){
|
||||||
|
tempAddress -= NUM_SAMPLES_PER_CHANNEL;
|
||||||
|
}
|
||||||
|
double *data = convertedStream_double.data();
|
||||||
|
data[numToGet-1-i] = get_filtered_sample(tempAddress, filter_mode, interval_samples);
|
||||||
|
//convertedStream_double.replace(i, buffer[tempAddress]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//update stream_index_at_last_call for next call
|
||||||
|
stream_index_at_last_call = tempAddress;
|
||||||
|
|
||||||
|
return &convertedStream_double;
|
||||||
|
}
|
||||||
|
|
||||||
|
int o1buffer::distanceFromMostRecentAddress(int index){
|
||||||
|
//Standard case. buffer[NUM_SAMPLES_PER_CHANNEL] not crossed between most recent and index's sample writes.
|
||||||
|
if(index < mostRecentAddress){
|
||||||
|
return mostRecentAddress - index;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Corner case. buffer[NUM_SAMPLES_PER_CHANNEL] boundary has been crossed.
|
||||||
|
if(index > mostRecentAddress){
|
||||||
|
//Two areas. 0 to mostRecentAddress, and index to the end of the buffer.
|
||||||
|
return mostRecentAddress + (NUM_SAMPLES_PER_CHANNEL - index);
|
||||||
|
}
|
||||||
|
|
||||||
|
//I guess the other corner case is when the addresses are the same.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//replace with get_filtered_sample
|
||||||
|
double o1buffer::get_filtered_sample(int index, int filter_type, int filter_size){
|
||||||
|
double accum = 0;
|
||||||
|
int currentPos = index - (filter_size / 2);
|
||||||
|
int end = currentPos + filter_size;
|
||||||
|
|
||||||
|
switch(filter_type){
|
||||||
|
case 0: //No filter
|
||||||
|
return buffer[index];
|
||||||
|
case 1: //Moving Average filter
|
||||||
|
if(currentPos < 0){
|
||||||
|
currentPos += NUM_SAMPLES_PER_CHANNEL;
|
||||||
|
}
|
||||||
|
if(end >= NUM_SAMPLES_PER_CHANNEL){
|
||||||
|
end -= NUM_SAMPLES_PER_CHANNEL;
|
||||||
|
}
|
||||||
|
while(currentPos != end){
|
||||||
|
accum += buffer[currentPos];
|
||||||
|
currentPos = (currentPos + 1) % NUM_SAMPLES_PER_CHANNEL;
|
||||||
|
}
|
||||||
|
return accum/((double)filter_size);
|
||||||
|
break;
|
||||||
|
default: //Default to "no filter"
|
||||||
|
return buffer[index];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef O1BUFFER_H
|
||||||
|
#define O1BUFFER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#define NUM_SAMPLES_PER_CHANNEL 7500000
|
||||||
|
|
||||||
|
|
||||||
|
class o1buffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit o1buffer();
|
||||||
|
~o1buffer();
|
||||||
|
void add(int value, int address);
|
||||||
|
int addVector(int *firstElement, int numElements);
|
||||||
|
int addVector(unsigned char *firstElement, int numElements);
|
||||||
|
int get(int address);
|
||||||
|
int mostRecentAddress = 0;
|
||||||
|
int stream_index_at_last_call = 0;
|
||||||
|
int distanceFromMostRecentAddress(int index);
|
||||||
|
std::vector<double> *getMany_double(int numToGet, int interval_samples, int delay_sample, int filter_mode);
|
||||||
|
std::vector<double> *getSinceLast(int feasible_window_begin, int feasible_window_end, int interval_samples, int filter_mode);
|
||||||
|
private:
|
||||||
|
int *buffer;
|
||||||
|
std::vector<double> convertedStream_double;
|
||||||
|
void updateMostRecentAddress(int newAddress);
|
||||||
|
double get_filtered_sample(int index, int filter_type, int filter_size);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // O1BUFFER_H
|
|
@ -1,13 +1,22 @@
|
||||||
#include "usbcallhandler.h"
|
#include "usbcallhandler.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "o1buffer.h"
|
||||||
|
|
||||||
|
//shared vars
|
||||||
|
o1buffer *internal_o1_buffer;
|
||||||
|
|
||||||
static void LIBUSB_CALL isoCallback(struct libusb_transfer * transfer){
|
static void LIBUSB_CALL isoCallback(struct libusb_transfer * transfer){
|
||||||
|
|
||||||
//Thread mutex??
|
//Thread mutex??
|
||||||
|
|
||||||
if(transfer->status!=LIBUSB_TRANSFER_CANCELLED){
|
if(transfer->status!=LIBUSB_TRANSFER_CANCELLED){
|
||||||
printf("Copy the data...\n");
|
printf("Copy the data...\n");
|
||||||
|
//TODO: a switch statement here to handle all the modes.
|
||||||
|
for(int i=0;i<transfer->num_iso_packets;i++){
|
||||||
|
unsigned char *packetPointer = libusb_get_iso_packet_buffer_simple(transfer, i);
|
||||||
|
internal_o1_buffer->addVector(packetPointer, 375);
|
||||||
|
}
|
||||||
printf("Re-arm the endpoint...\n");
|
printf("Re-arm the endpoint...\n");
|
||||||
int error = libusb_submit_transfer(transfer);
|
int error = libusb_submit_transfer(transfer);
|
||||||
if(error){
|
if(error){
|
||||||
|
@ -20,8 +29,8 @@ static void LIBUSB_CALL isoCallback(struct libusb_transfer * transfer){
|
||||||
void usb_polling_function(libusb_context *ctx){
|
void usb_polling_function(libusb_context *ctx){
|
||||||
printf("usb_polling_function thread spawned\n");
|
printf("usb_polling_function thread spawned\n");
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
tv.tv_sec = 2;
|
tv.tv_sec = 0;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = ISO_PACKETS_PER_CTX*4000;
|
||||||
while(1){
|
while(1){
|
||||||
printf("usb_polling_function begin loop\n");
|
printf("usb_polling_function begin loop\n");
|
||||||
if(libusb_event_handling_ok(ctx)){
|
if(libusb_event_handling_ok(ctx)){
|
||||||
|
@ -39,6 +48,8 @@ usbCallHandler::usbCallHandler(unsigned short VID_in, unsigned short PID_in)
|
||||||
pipeID[k] = 0x81+k;
|
pipeID[k] = 0x81+k;
|
||||||
printf("pipeID %d = %d\n", k, pipeID[k]);
|
printf("pipeID %d = %d\n", k, pipeID[k]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal_o1_buffer = new o1buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
usbCallHandler::~usbCallHandler(){
|
usbCallHandler::~usbCallHandler(){
|
||||||
|
|
|
@ -33,6 +33,7 @@ typedef struct uds{
|
||||||
|
|
||||||
} unified_debug;
|
} unified_debug;
|
||||||
|
|
||||||
|
|
||||||
class usbCallHandler
|
class usbCallHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in New Issue