API appears to actually store iso endpoint data

This commit is contained in:
Chris Esposito 2018-04-01 08:05:52 +11:00
parent e9d84cd963
commit 36b9be5837
7 changed files with 231 additions and 6 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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];
}
}

View File

@ -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

View File

@ -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(){

View File

@ -33,6 +33,7 @@ typedef struct uds{
} unified_debug; } unified_debug;
class usbCallHandler class usbCallHandler
{ {
public: public: