/******************************************************************************!
* \file usbscope.cpp
* \author Sebastien Beaugrand
* \sa http://beaugrand.chez.com/
* \copyright CeCILL 2.1 Free Software license
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include "usb/device.h"
#include "x11Scope.h"
#define VENDOR_ID 0x4242
#define DEVICE_ID 0x0002
#define EP_ADDR (LIBUSB_ENDPOINT_IN | 1) // lsusb -v | grep bEndpointAddress
#define BUFF_SIZE 8 // wMaxPacketSize
USB::Device* gDev = NULL;
FILE* gFile1 = NULL;
FILE* gFile2 = NULL;
X11::Callback* gLoop = NULL;
X11::Scope* gScope = NULL;
/******************************************************************************!
* \fn closeAll
******************************************************************************/
void closeAll()
{
if (gScope != NULL) {
delete gScope;
}
if (gLoop != NULL) {
delete gLoop;
}
if (gFile1 != NULL) {
fclose(gFile1);
}
if (gFile2 != NULL) {
fclose(gFile2);
}
if (gDev != NULL) {
gDev->close();
delete gDev;
}
}
/******************************************************************************!
* \fn status
******************************************************************************/
void status(const char* str, int code)
{
if (code < 0) {
fprintf(stderr, "error: %s (err=%d)\n", str, code);
closeAll();
exit(EXIT_FAILURE);
} else {
fprintf(stderr, "%s: %d\n", str, code);
}
}
/******************************************************************************!
* \fn callback
******************************************************************************/
void callback(struct libusb_transfer* transfer)
{
static struct timeval tv;
static time_t tstart = 0;
static suseconds_t ustart = -1;
static double time;
static double val1;
static double val2;
gettimeofday(&tv, NULL);
if (tstart == 0) {
tstart = tv.tv_sec;
ustart = tv.tv_usec;
}
tv.tv_sec -= tstart;
if (tv.tv_usec >= ustart) {
tv.tv_usec -= ustart;
} else {
tv.tv_sec -= 1;
tv.tv_usec += 1000000 - ustart;
}
time = tv.tv_sec + tv.tv_usec / 1000000.0;
// 0.92 :
// http://www.reality.be/elo/labos3/files/usb-scope.zip
// vi usb-scope/UsbApp/usbscope.cs +105
val1 = ((transfer->buffer[0] << 8) + transfer->buffer[1]) * 0.00092;
fprintf(gFile1, "%ld.%06ld %.3f\n", tv.tv_sec, tv.tv_usec, val1);
if (gFile2 != NULL) {
val2 = ((transfer->buffer[2] << 8) + transfer->buffer[3]) * 0.00092;
fprintf(gFile2, "%ld.%06ld %.3f\n", tv.tv_sec, tv.tv_usec, val2);
}
if (gFile2 != NULL) {
gScope->drawPoints(time, val1, val2);
} else {
gScope->drawPoints(time, val1);
}
gDev->submit(transfer);
}
/******************************************************************************!
* \class LoopCallback
******************************************************************************/
class LoopCallback : public X11::Callback
{
public:
int loop(const X11::Event*)
{
int r = libusb_handle_events(NULL);
if (r < 0) {
status("libusb_handle_events", r);
}
return 0;
}
};
/******************************************************************************!
* \fn main
******************************************************************************/
int main(int argc, char** argv)
{
if (argc != 2 && argc != 3) {
printf("Usage: %s <file1> [file2]\n", argv[0]);
return EXIT_FAILURE;
}
gDev = new USB::Device();
gDev->open(VENDOR_ID, DEVICE_ID);
gDev->submit(EP_ADDR, BUFF_SIZE, callback);
gFile1 = fopen(argv[1], "w");
status("fopen 1", (gFile1 == NULL) ? -1 : 0);
if (argc == 3) {
gFile2 = fopen(argv[2], "w");
status("fopen 2", (gFile2 == NULL) ? -1 : 0);
}
gLoop = new LoopCallback;
gScope = new X11::Scope;
gScope->run(gLoop,
(int (X11::Callback::*)(const X11::Event*))
& LoopCallback::loop);
closeAll();
return EXIT_SUCCESS;
}