diff --git a/Matlab_Octave_API/___librador/demo/librademo/librademo b/Matlab_Octave_API/___librador/demo/librademo/librademo index 2d5a474b..dc07c54c 100755 Binary files a/Matlab_Octave_API/___librador/demo/librademo/librademo and b/Matlab_Octave_API/___librador/demo/librademo/librademo differ diff --git a/Matlab_Octave_API/___librador/librador/Makefile b/Matlab_Octave_API/___librador/librador/Makefile index 7c91b0e6..f7388bba 100644 --- a/Matlab_Octave_API/___librador/librador/Makefile +++ b/Matlab_Octave_API/___librador/librador/Makefile @@ -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 diff --git a/Matlab_Octave_API/___librador/librador/librador.pro b/Matlab_Octave_API/___librador/librador/librador.pro index 7fb989c3..9e6ebb72 100644 --- a/Matlab_Octave_API/___librador/librador/librador.pro +++ b/Matlab_Octave_API/___librador/librador/librador.pro @@ -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 { diff --git a/Matlab_Octave_API/___librador/librador/o1buffer.cpp b/Matlab_Octave_API/___librador/librador/o1buffer.cpp new file mode 100644 index 00000000..1829af13 --- /dev/null +++ b/Matlab_Octave_API/___librador/librador/o1buffer.cpp @@ -0,0 +1,173 @@ +#include "o1buffer.h" +#include +#include + + +//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 *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 *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= 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]; + } +} diff --git a/Matlab_Octave_API/___librador/librador/o1buffer.h b/Matlab_Octave_API/___librador/librador/o1buffer.h new file mode 100644 index 00000000..618fd13e --- /dev/null +++ b/Matlab_Octave_API/___librador/librador/o1buffer.h @@ -0,0 +1,30 @@ +#ifndef O1BUFFER_H +#define O1BUFFER_H + +#include + +#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 *getMany_double(int numToGet, int interval_samples, int delay_sample, int filter_mode); + std::vector *getSinceLast(int feasible_window_begin, int feasible_window_end, int interval_samples, int filter_mode); +private: + int *buffer; + std::vector convertedStream_double; + void updateMostRecentAddress(int newAddress); + double get_filtered_sample(int index, int filter_type, int filter_size); +}; + +#endif // O1BUFFER_H diff --git a/Matlab_Octave_API/___librador/librador/usbcallhandler.cpp b/Matlab_Octave_API/___librador/librador/usbcallhandler.cpp index f59aa917..a139ff17 100644 --- a/Matlab_Octave_API/___librador/librador/usbcallhandler.cpp +++ b/Matlab_Octave_API/___librador/librador/usbcallhandler.cpp @@ -1,13 +1,22 @@ #include "usbcallhandler.h" #include +#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;inum_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(){ diff --git a/Matlab_Octave_API/___librador/librador/usbcallhandler.h b/Matlab_Octave_API/___librador/librador/usbcallhandler.h index eac9c53a..9cb9c0e4 100644 --- a/Matlab_Octave_API/___librador/librador/usbcallhandler.h +++ b/Matlab_Octave_API/___librador/librador/usbcallhandler.h @@ -33,6 +33,7 @@ typedef struct uds{ } unified_debug; + class usbCallHandler { public: