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
|
||||
|
||||
SOURCES = librador.cpp \
|
||||
o1buffer.cpp \
|
||||
usbcallhandler.cpp
|
||||
OBJECTS = librador.o \
|
||||
o1buffer.o \
|
||||
usbcallhandler.o
|
||||
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 \
|
||||
|
@ -239,7 +241,9 @@ DIST = /home/esposch/Qt/5.10.0/gcc_64/mkspecs/features/spec_pre.prf \
|
|||
librador.pro librador.h \
|
||||
librador_global.h \
|
||||
librador_internal.h \
|
||||
o1buffer.h \
|
||||
usbcallhandler.h librador.cpp \
|
||||
o1buffer.cpp \
|
||||
usbcallhandler.cpp
|
||||
QMAKE_TARGET = rador
|
||||
DESTDIR =
|
||||
|
@ -657,8 +661,8 @@ distdir: FORCE
|
|||
@test -d $(DISTDIR) || mkdir -p $(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 librador.h librador_global.h librador_internal.h usbcallhandler.h $(DISTDIR)/
|
||||
$(COPY_FILE) --parents librador.cpp usbcallhandler.cpp $(DISTDIR)/
|
||||
$(COPY_FILE) --parents librador.h librador_global.h librador_internal.h o1buffer.h usbcallhandler.h $(DISTDIR)/
|
||||
$(COPY_FILE) --parents librador.cpp o1buffer.cpp usbcallhandler.cpp $(DISTDIR)/
|
||||
|
||||
|
||||
clean: compiler_clean
|
||||
|
@ -737,8 +741,12 @@ librador.o: librador.cpp librador.h \
|
|||
../../../Desktop_Interface/build_linux/libusb/libusb.h
|
||||
$(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 \
|
||||
../../../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
|
||||
|
||||
####### Install
|
||||
|
|
|
@ -30,12 +30,14 @@ DEPENDPATH += ../../../Desktop_Interface
|
|||
|
||||
SOURCES += \
|
||||
librador.cpp \
|
||||
o1buffer.cpp \
|
||||
usbcallhandler.cpp
|
||||
|
||||
HEADERS += \
|
||||
librador.h \
|
||||
librador_global.h \
|
||||
librador_internal.h \
|
||||
o1buffer.h \
|
||||
usbcallhandler.h
|
||||
|
||||
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 <stdio.h>
|
||||
|
||||
#include "o1buffer.h"
|
||||
|
||||
//shared vars
|
||||
o1buffer *internal_o1_buffer;
|
||||
|
||||
static void LIBUSB_CALL isoCallback(struct libusb_transfer * transfer){
|
||||
|
||||
//Thread mutex??
|
||||
|
||||
if(transfer->status!=LIBUSB_TRANSFER_CANCELLED){
|
||||
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");
|
||||
int error = libusb_submit_transfer(transfer);
|
||||
if(error){
|
||||
|
@ -20,8 +29,8 @@ static void LIBUSB_CALL isoCallback(struct libusb_transfer * transfer){
|
|||
void usb_polling_function(libusb_context *ctx){
|
||||
printf("usb_polling_function thread spawned\n");
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 2;
|
||||
tv.tv_usec = 0;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = ISO_PACKETS_PER_CTX*4000;
|
||||
while(1){
|
||||
printf("usb_polling_function begin loop\n");
|
||||
if(libusb_event_handling_ok(ctx)){
|
||||
|
@ -39,6 +48,8 @@ usbCallHandler::usbCallHandler(unsigned short VID_in, unsigned short PID_in)
|
|||
pipeID[k] = 0x81+k;
|
||||
printf("pipeID %d = %d\n", k, pipeID[k]);
|
||||
}
|
||||
|
||||
internal_o1_buffer = new o1buffer();
|
||||
}
|
||||
|
||||
usbCallHandler::~usbCallHandler(){
|
||||
|
|
|
@ -33,6 +33,7 @@ typedef struct uds{
|
|||
|
||||
} unified_debug;
|
||||
|
||||
|
||||
class usbCallHandler
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue