ACQ2XX_API
streamer.cpp
Go to the documentation of this file.
00001 /* ------------------------------------------------------------------------- */
00002 /* file streamer.cpp                                                         */
00003 /* ------------------------------------------------------------------------- */
00004 /*   Copyright (C) 2009 Peter Milne, D-TACQ Solutions Ltd
00005  *                      <Peter dot Milne at D hyphen TACQ dot com>
00006 
00007  This program is free software; you can redistribute it and/or modify
00008  it under the terms of Version 2 of the GNU General Public License
00009  as published by the Free Software Foundation;
00010 
00011  This program is distributed in the hope that it will be useful,
00012  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  GNU General Public License for more details.
00015 
00016  You should have received a copy of the GNU General Public License
00017  along with this program; if not, write to the Free Software
00018  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                   */
00019 /* ------------------------------------------------------------------------- */
00020 
00021 /** @file streamer.cpp example application streams data from dt100d port.
00022  - program auto-detects card type:
00023  - nchannels 32/64/96
00024  - word_size 2/3/4
00025  - lock-in or normal
00026  - IF lock-in : reference selection
00027 
00028  - default output option prints mean (64) value of each channel in columns.
00029  - use cut to select channels of interest.
00030  - it's trivial to collect an bunch of data to plot in a math tool like gnu-octave.
00031  - for large volume data collection, use "-o dirfile" option.
00032   - DirFile is a simple binary file format 
00033   - essentially a directory with a binary file per channel.
00034   - Format:http://getdata.sourceforge.net/dirfile.html 
00035   - Plot:http://kst.kde.org/handbook/index.html
00036 
00037 <pre>
00038 Usage: streamer [OPTION...]
00039   -f, --device=STRING
00040   -b, --board=STRING
00041   -v, --verbose=INT
00042   --version
00043   -T, --showtags
00044   -x, --showhex
00045   -n, --nomean
00046   -m, --mean
00047   -o dirfile : output in DirFile format (use kst to view)
00048   --time-frames
00049 
00050 Help options:
00051   -?, --help              Show this help message
00052   --usage                 Display brief usage message
00053 
00054 
00055 Example usage:
00056 [peter@rhum API]$  ./x86/bin/streamer -T -f 192.168.1.216 | cut -f 1-8 | head -n 5
00057          0                 0    -17067  -18570       0       0  -17009  -18589
00058          1                 0    -22293  -24254       0      -1  -22217  -24279
00059          2                 0    -22290  -24256       0      -1  -22216  -24282
00060          3                 0    -22290  -24257       0      -1  -22216  -24282
00061          4                 0    -22291  -24255       0      -1  -22217  -24281
00062 
00063 </pre>
00064  */
00065 
00066 #include <popt.h>
00067 
00068 #include <sys/stat.h>
00069 #include <sys/types.h>
00070 #include <sys/time.h>
00071 #include <errno.h>
00072 
00073 #include "local.h"
00074 #include "acq2xx_api.h"
00075 #include "acq_transport.h"
00076 #include "AcqType.h"
00077 #include "Frame.h"
00078 
00079 #include "DataStreamer.h"
00080 #include "DirfileFrameHandler.h"
00081 
00082 int acq200_debug;
00083 int timeout;
00084 char* device;
00085 int do_shell;
00086 
00087 #define RETERR(cmd) if (STATUS_ERR(rc = cmd)) {         \
00088         err("failed: \"%s\" code:%d", #cmd, rc);        \
00089         return rc;      \
00090 }
00091 
00092 
00093 
00094 static int show_mean = 1;
00095 static int format_hex;
00096 static int show_tags;
00097 static char* outbase;
00098 
00099 static int time_frames;
00100 
00101 #define US      1000000
00102 
00103 class FrameTimer : public FrameHandler {
00104         struct timeval old_time;
00105         unsigned old_frame;
00106         unsigned long long old_sample;
00107 
00108 
00109         double tv_difftime(struct timeval& old_time, struct timeval& new_time)
00110         {
00111                 double dt = (new_time.tv_sec - old_time.tv_sec) * US;
00112 
00113                 if (old_time.tv_usec > new_time.tv_usec){
00114                         dt -= US;
00115                         dt += (US + new_time.tv_usec) - old_time.tv_usec;
00116                 }else{
00117                         dt += new_time.tv_usec - old_time.tv_usec;
00118                 }
00119                 return dt/US;
00120         }
00121 
00122 public:
00123         FrameTimer() {
00124                 old_time.tv_sec = old_time.tv_usec = 0;
00125                 old_frame = 0;
00126                 old_sample = 0;
00127                 fprintf(stderr, "FrameTimer: ID\tSAMPLE\tDT\tFPS\n");
00128         }
00129         virtual void onFrame(
00130                         Acq2xx& _card, const AcqType& _acqType,
00131                         const Frame* frame)
00132         {
00133                 struct timeval new_time;
00134                 gettimeofday(&new_time, 0);
00135                 unsigned long long new_sample = frame->getStartSampleNumber();
00136                 double dt, fps;
00137                 unsigned new_frame = frame->getID();
00138 
00139                 if (old_time.tv_sec == 0){
00140                         dt = fps = 0;
00141                 }else{
00142                         dt = tv_difftime(old_time, new_time);
00143                         fps = (new_frame - old_frame)/dt;
00144                 }
00145                 printf("%5d\t%10lld\t%6.4f\t%6.2f\t", 
00146                        new_frame, new_sample, dt, fps);
00147                 old_time = new_time;
00148                 old_sample = new_sample;
00149                 old_frame = new_frame;
00150         }
00151 };
00152 
00153 int main(int argc, const char** argv)
00154 {
00155         struct poptOption opt_table[] = {
00156                 { "device",     'f', POPT_ARG_STRING, &device,          'f' },
00157                 { "board",      'b', POPT_ARG_STRING, &device,          'b' },
00158                 { "verbose",    'v', POPT_ARG_INT,    &acq200_debug,    0   },
00159                 { "version",    0,   POPT_ARG_NONE,   0,                'V' },
00160                 { "showtags",   'T', POPT_ARG_INT,   &show_tags,        'T'  },
00161                 { "showhex",    'x', POPT_ARG_NONE,   0,                'x' },
00162                 { "nomean",     'n', POPT_ARG_NONE,   0,                'n' },
00163                 { "mean",       'm', POPT_ARG_INT,   &show_mean,        'm' },
00164                 { "outbase",    'o', POPT_ARG_STRING, &outbase,         0 },
00165                 { "time-frames", 0,  POPT_ARG_INT,    &time_frames,     0 },
00166                 POPT_AUTOHELP
00167                 POPT_TABLEEND           
00168         };
00169         int rc;
00170         poptContext opt_context = 
00171                 poptGetContext(argv[0], argc, argv, opt_table, 0);
00172 
00173         while ( (rc = poptGetNextOpt(opt_context)) > 0 ){
00174                 switch(rc){
00175                 case 'x':
00176                         format_hex = 1;
00177                         break;
00178 
00179                 default:
00180                         break;
00181                 }
00182         }       
00183 
00184         if (device == 0){
00185                 err("streamer [opts]");
00186                 return 1;
00187         }
00188 
00189         Transport *t = Transport::getTransport(device); 
00190         Acq2xx card(t);
00191 
00192         DataStreamer* dataStreamer = DataStreamer::create(
00193                                 card, AcqType::getAcqType(card));
00194 
00195 
00196         if (show_tags){
00197                 /* must be first to secure LH columns of report .. */
00198                 dataStreamer->addFrameHandler(
00199                         DataStreamer::createTagHandler(show_tags));
00200         }
00201 
00202         if (time_frames){
00203                 dataStreamer->addFrameHandler(new FrameTimer());
00204         }
00205         if (show_mean){
00206                 dataStreamer->addFrameHandler(
00207                         DataStreamer::createMeanHandler(
00208                                 AcqType::getAcqType(card), format_hex));
00209         }
00210         if (show_mean || show_tags||time_frames){
00211                 dataStreamer->addFrameHandler(
00212                         DataStreamer::createNewlineHandler());         
00213         }
00214         if (outbase){
00215                 if (mkdir(outbase, 0777) == 0 || errno == EEXIST){
00216                         ;
00217                 }else{
00218                         err("failed to mkdir(\"%s\")", outbase);
00219                         exit(-errno);
00220                 }
00221                 dataStreamer->addFrameHandler(
00222                         DirfileFrameHandler::create(
00223                                 AcqType::getAcqType(card), outbase));
00224         }
00225         return dataStreamer->streamData();
00226 
00227         /* t, dataStreamer deleted on exit() */
00228 }