ARPDAS_QNX6 1.0
DG.cc
Go to the documentation of this file.
00001 /* DG.c */
00002 #include <errno.h>
00003 #include <sys/uio.h>
00004 #include "DG.h"
00005 
00006 data_generator::data_generator(int nQrows, int low_water)
00007     : data_queue(nQrows,low_water) {
00008   dg_bfr_fd = -1;
00009   quit = false;
00010   started = false;
00011   regulated = false;
00012   regulation_optional = true;
00013   autostart = false;
00014 }
00015 
00016 data_generator::~data_generator() {}
00017 
00018 /**
00019  * Assumes tm_info is defined
00020  */
00021 void data_generator::init(int collection) {
00022   data_queue::init();
00023   dg_bfr_fd = open(tm_dev_name("TM/DG"), collection ? O_WRONLY|O_NONBLOCK : O_WRONLY );
00024   if (dg_bfr_fd < 0) nl_error(3, "Unable to open TM/DG: %d", errno );
00025   tm_hdr_t hdr = { TMHDR_WORD, TMTYPE_INIT };
00026   iov_t iov[2];
00027   SETIOV(&iov[0], &hdr, sizeof(hdr));
00028   SETIOV(&iov[1], &tm_info, sizeof(tm_info));
00029   int rc = writev( dg_bfr_fd, iov, 2);
00030   check_writev( rc, sizeof(tm_info)+sizeof(hdr), "sending TMTYPE_INIT" );
00031   dispatch = new DG_dispatch();
00032   cmd = new DG_cmd(this);
00033   cmd->attach();
00034   tmr = new DG_tmr(this);
00035   tmr->attach();
00036   row_period_nsec_default = tmi(nsecsper)*(uint64_t)1000000000L/tmi(nrowsper);
00037   row_period_nsec_current = row_period_nsec_default;
00038 }
00039 
00040 void data_generator::transmit_data( int single_row ) {
00041   // We can read from the queue without locking
00042   // But we need to lock when we reference dg_bfr_fd
00043   dq_tstamp_ref *dqts;
00044   dq_data_ref *dqdr;
00045   // nl_error( 0, "transmit_data(%s)", single_row ? "single" : "all" );
00046   int rc;
00047   tm_hdrs_t hdrs;
00048   hdrs.s.hdr.tm_id = TMHDR_WORD;
00049   iov_t iov[3];
00050   while ( first_dqr ) {
00051     switch ( first_dqr->type ) {
00052       case dq_tstamp:
00053         dqts = (dq_tstamp_ref *)first_dqr;
00054         hdrs.s.hdr.tm_type = TMTYPE_TSTAMP;
00055         SETIOV(&iov[0], &hdrs, sizeof(tm_hdr_t));
00056         SETIOV(&iov[1], &dqts->TS, sizeof(dqts->TS));
00057         lock(__FILE__, __LINE__);
00058         if ( dg_bfr_fd != -1 ) {
00059           rc = writev(dg_bfr_fd, iov, 2);
00060           check_writev( rc, sizeof(tm_hdr_t)+sizeof(dqts->TS),
00061              "transmitting tstamp" );
00062         }
00063         unlock();
00064         retire_tstamp(dqts);
00065         break;
00066       case dq_data:
00067         dqdr = (dq_data_ref *)first_dqr;
00068         if (dqdr->n_rows == 0) {
00069           if (dqdr->next_dqr) retire_rows(dqdr, 0);
00070           else return;
00071         } else {
00072           hdrs.s.hdr.tm_type = output_tm_type;
00073           int n_rows = single_row ? 1 : dqdr->n_rows;
00074           hdrs.s.u.dhdr.n_rows = n_rows;
00075           hdrs.s.u.dhdr.mfctr = dqdr->MFCtr_start;
00076           hdrs.s.u.dhdr.rownum = dqdr->row_start;
00077           SETIOV(&iov[0], &hdrs, nbDataHdr);
00078           int n_iov;
00079           if ( dqdr->Qrow + n_rows < total_Qrows ) {
00080             SETIOV(&iov[1], row[dqdr->Qrow], n_rows * nbQrow );
00081             n_iov = 2;
00082           } else {
00083             int n_rows1 = total_Qrows - dqdr->Qrow;
00084             SETIOV(&iov[1], row[dqdr->Qrow], n_rows1 * nbQrow );
00085             int n_rows2 = n_rows - n_rows1;
00086             SETIOV(&iov[2], row[0], n_rows2 * nbQrow );
00087             n_iov = 3;
00088           }
00089           lock(__FILE__,__LINE__);
00090           if ( dg_bfr_fd != -1 ) {
00091             rc = writev(dg_bfr_fd, iov, n_iov);
00092             unlock();
00093             check_writev( rc, nbDataHdr + n_rows * nbQrow,
00094                "transmitting data" );
00095           } else unlock();
00096           retire_rows(dqdr, n_rows);
00097           if ( single_row ) return;
00098         }
00099         break;
00100       default:
00101         nl_error(4, "Invalid type in transmit_data" );
00102     }
00103   }
00104 }
00105 
00106 void data_generator::check_writev( int rc, int wr_size, const char *where ) {
00107   if ( rc < 0 ) nl_error( 3, "Error %d %s", errno, where );
00108   else if ( rc != wr_size )
00109     nl_error( 3, "writev %d, not %d, %s", rc, wr_size, where );
00110 }
00111 
00112 /**
00113  * Control initialization
00114  * This is how 
00115  */
00116 void data_generator::operate() {
00117   if ( autostart ) tm_start(1);
00118   dispatch->Loop();
00119 }
00120 
00121 /**
00122  Interperet data generator commands: I need to abstract the "signal handlers" operation.
00123  It appears that the key notifications are:
00124   Start
00125   Stop
00126   Quit
00127   Change to unregulated output (fast forward)
00128  
00129  TM start: "TMc"
00130     Set start condition
00131     If regulated, program timer
00132     else stop timer
00133     if ext_stop, signal handlers
00134 TM end/stop "TMe"
00135     Set stop condition
00136     stop timer
00137     if ext_time, signal handlers
00138 Quit: ""
00139     Set stop and quit conditions
00140     stop timer
00141     if ext_stop or ext_time, signal handlers
00142 TM play "TM>"
00143     set regulated
00144     set row_rate to default
00145     if stopped, do start
00146     else reprogram timer
00147 TM fast forward "TM}"
00148     if regulation_optional
00149       stop timer
00150       set unregulated
00151       if stopped, do start
00152       else if ext_time, signal handlers
00153 TM faster/slower "TM+" "TM-"
00154     if regulation_optional
00155       if stopped
00156         do play
00157       else if regulated
00158         increase/decrease row_rate
00159         program timer
00160 TM single step "TMs"
00161 
00162 Command Summary:
00163   "" Quit
00164   "TMc" TM Start
00165   "TMe" TM End/Stop/Pause
00166   "TMs" Single Step
00167   "TM>" Play
00168   "TM+" Faster
00169   "TM-" Slower
00170   "TM}" Fast Forward
00171   
00172   Still need to add the search functions:
00173  TM Advance to MFCtr
00174  TM Advance to Time
00175  */
00176 int data_generator::execute(const char *cmd) {
00177   if (cmd[0] == '\0') {
00178     tmr->settime(0);
00179     lock(__FILE__,__LINE__);
00180     started = false;
00181     quit = true;
00182     if ( dg_bfr_fd != -1 ) {
00183       close(dg_bfr_fd);
00184       dg_bfr_fd = -1;
00185     }
00186     unlock();
00187     nl_error( -2, "Received Quit" );
00188     dispatch->ready_to_quit();
00189     event(dg_event_quit);
00190     return 1;
00191   }
00192   if ( cmd[0] == 'T' && cmd[1] == 'M' ) {
00193     switch ( cmd[2] ) {
00194       case 'c': tm_start(1); break;
00195       case 'e': tm_stop(); break;
00196       case 's':
00197         lock(__FILE__,__LINE__);
00198         if (!started) {
00199           regulated = true;
00200           row_period_nsec_current = 0;
00201           tm_start(0);
00202         } else {
00203           regulated = true;
00204           if ( row_period_nsec_current ) {
00205             row_period_nsec_current = 0;
00206             tmr->settime(0);
00207           }
00208           unlock();
00209         }
00210         service_row_timer(); /* single_step(); */
00211         break;
00212       case '>': tm_play(); break; // play
00213       case '+':
00214         if (regulation_optional) {
00215           lock(__FILE__,__LINE__);
00216           if (!started || ( regulated && row_period_nsec_current == 0) )
00217             tm_play(0);
00218           else if ( regulated ) {
00219             row_period_nsec_current = row_period_nsec_current * 2 / 3;
00220             if ( row_period_nsec_current < tmr->timer_resolution_nsec ) {
00221               regulated = false;
00222               tmr->settime(0);
00223               unlock();
00224               event(dg_event_fast);
00225             } else {
00226               tmr->settime(row_period_nsec_current);
00227               unlock();
00228             }
00229           } else unlock();
00230         }
00231         break;
00232       case '-': // slower
00233         if (regulation_optional) {
00234           lock(__FILE__,__LINE__);
00235           if (!started) tm_play(0);
00236           else {
00237             row_period_nsec_current = row_period_nsec_current * 3 / 2;
00238             tmr->settime(row_period_nsec_current);
00239             regulated = true;
00240             unlock();
00241           }
00242         }
00243         break;
00244       case '}': // fast forward
00245         if (regulation_optional) {
00246           lock(__FILE__,__LINE__);
00247           tmr->settime(0);
00248           regulated = false;
00249           if (started) {
00250             unlock();
00251             event(dg_event_fast);
00252           } else tm_start(0);
00253         }
00254         break;
00255       default:
00256         nl_error(2,"Invalid TM command in data_generator::execute: '%s'", cmd );
00257         break;
00258     }
00259   } else nl_error(2, "Invalid command in data_generator::execute: '%s'", cmd );
00260   return 0;
00261 }
00262 
00263 void data_generator::event(enum dg_event evt) {}
00264 
00265 void data_generator::tm_start(int lock_needed) {
00266   if (lock_needed) lock(__FILE__,__LINE__);
00267   started = true;
00268   if ( regulated ) tmr->settime(row_period_nsec_current);
00269   else tmr->settime( 0 );
00270   unlock();
00271   event( dg_event_start );
00272 }
00273 
00274 void data_generator::tm_play(int lock_needed) {
00275   if (lock_needed) lock(__FILE__,__LINE__);
00276   regulated = true;
00277   row_period_nsec_current = row_period_nsec_default;
00278   if ( started ) {
00279     tmr->settime(row_period_nsec_current);
00280     unlock();
00281   } else tm_start(0); // don't need to re-lock(), but will unlock()
00282 }
00283 
00284 void data_generator::tm_stop() {
00285   lock(__FILE__,__LINE__);
00286   started = false;
00287   unlock();
00288   tmr->settime(0);
00289   event(dg_event_stop);
00290 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines