ARPDAS_QNX6 1.0
|
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 }