00001 00003 /* 00004 FAU Discrete Event Systems Library (libfaudes) 00005 00006 Copyright (C) 2008 Thomas Moor 00007 00008 */ 00009 00010 00011 // load configuration 00012 #include "corefaudes.h" 00013 00014 00015 #include "sp_dplpexecutor.h" 00016 #include <iostream> 00017 00018 namespace faudes { 00019 00020 // constructor 00021 DeviceExecutor::DeviceExecutor(void) : ProposingExecutor() , pDevice(0) { 00022 mMaxSyncGap=10*tpTime::Step; 00023 } 00024 00025 // cdestructor 00026 DeviceExecutor::~DeviceExecutor(void) { 00027 } 00028 00029 // set io device 00030 void DeviceExecutor::Devicep(vDevice* dev) { 00031 pDevice=dev; 00032 mSyncError=false; 00033 #ifdef FAUDES_PLUGIN_IODEVICE 00034 if(!dev) return; 00035 pDevice->Reset(); 00036 #endif 00037 } 00038 00039 // start the device 00040 void DeviceExecutor::DeviceStart(void) { 00041 #ifdef FAUDES_PLUGIN_IODEVICE 00042 if(!pDevice) return; 00043 pDevice->Start(); 00044 #endif 00045 } 00046 00047 // stop the device 00048 void DeviceExecutor::DeviceStop(void) { 00049 #ifdef FAUDES_PLUGIN_IODEVICE 00050 if(!pDevice) return; 00051 pDevice->Stop(); 00052 #endif 00053 } 00054 00055 // clear static data 00056 void DeviceExecutor::Clear(void){ 00057 Reset(); 00058 ProposingExecutor::Clear(); 00059 } 00060 00061 // clear dynamic data 00062 void DeviceExecutor::Reset(long int seed){ 00063 #ifdef FAUDES_PLUGIN_IODEVICE 00064 if(pDevice) pDevice->Reset(); 00065 #endif 00066 ProposingExecutor::Reset(seed); 00067 mSyncError=false; 00068 } 00069 00070 //ExecuteEvent 00071 bool DeviceExecutor::ExecuteEvent(Idx event){ 00072 FD_DS("DeviceExecutor::ExecuteEvent(): "<< EventName(event)); 00073 /* 00074 #ifdef FAUDES_PLUGIN_IODEVICE 00075 // sync time 00076 if(pDevice) SyncStep(0); 00077 #endif 00078 */ 00079 // execute event 00080 bool res=ProposingExecutor::ExecuteEvent(event); 00081 /* 00082 #ifdef FAUDES_PLUGIN_IODEVICE 00083 // pass on to callbacks 00084 if(res && pDevice) pDevice->WriteActuator(event); 00085 #endif 00086 */ 00087 // report 00088 return res; 00089 } 00090 00091 00092 //SyncTime() 00093 bool DeviceExecutor::SyncTime(void){ 00094 00095 // no plugin, no run 00096 #ifndef FAUDES_PLUGIN_IODEVICE 00097 return false; 00098 #else 00099 00100 // no device, no run 00101 if(!pDevice) return false; 00102 00103 // figure situation 00104 tpTime::Type devNow=pDevice->CurrentTime(); 00105 tpTime::Type genNow=CurrentTime(); 00106 tpTime::Type syncTime=devNow-genNow; 00107 tpTime::Type propTime=ProposeNextTransition().Time; 00108 00109 // report 00110 FD_DS_SYNC("DeviceExecutor::SyncTime(): device time " << devNow << " gen time " << genNow); 00111 00112 // time sync: no chance since generator is ahead 00113 if(syncTime < -mMaxSyncGap) { 00114 FD_DS_SYNC("DeviceExecutor::SyncTime(): sync error: gen time ahead"); 00115 mSyncError=true; 00116 pDevice->Reset(); 00117 return false; 00118 } 00119 00120 // time sync: check whether proposal allows for sync 00121 if(syncTime - mMaxSyncGap > propTime || propTime==tpTime::UnDef) { 00122 FD_DS_SYNC("DeviceExecutor::SyncTime(): sync error: cannot sync enough time"); 00123 mSyncError=true; 00124 pDevice->Reset(); 00125 return false; 00126 } 00127 00128 // adjust by proposal 00129 if(syncTime > propTime) { 00130 FD_DS_SYNC("DeviceExecutor::SyncTime(): adjust by proposal"); 00131 syncTime=propTime; 00132 } 00133 00134 // time sync: pass generator time 00135 FD_DS_SYNC("DeviceExecutor::SyncTime(): generator to pass " << syncTime); 00136 if(!ProposingExecutor::ExecuteTime(syncTime)) { 00137 tpTime::Type maxsync=EnabledTime().UB(); 00138 if(maxsync >= syncTime-mMaxSyncGap) { 00139 syncTime=maxsync; 00140 } 00141 FD_DS_SYNC("DeviceExecutor::SyncTime(): retry: generator to pass " << syncTime); 00142 if(!ProposingExecutor::ExecuteTime(syncTime)) { 00143 FD_DS_SYNC("DeviceExecutor::SyncTime(): exec error"); 00144 mSyncError=true; 00145 pDevice->Reset(); 00146 return false; 00147 } 00148 }; 00149 00150 // done 00151 FD_DS_SYNC("DeviceExecutor::SyncTime(): ok"); 00152 return true; 00153 00154 #endif 00155 } 00156 00157 00158 //SyncEvents() 00159 Idx DeviceExecutor::SyncEvents(void){ 00160 00161 // no plugin, no run 00162 #ifndef FAUDES_PLUGIN_IODEVICE 00163 return 0; 00164 #else 00165 00166 // no device, no run 00167 if(!pDevice) return 0; 00168 00169 00170 // check and execute scheduled event 00171 const TimedEvent& proposedTrans=ProposeNextTransition(); 00172 if(proposedTrans.Time==0 && proposedTrans.Event!=0) { 00173 FD_DS_SYNC("DeviceExecutor::SyncEvents(): scheduled event: " << EventName(proposedTrans.Event)); 00174 ProposingExecutor::ExecuteEvent(proposedTrans.Event); 00175 if(pDevice->Actuators().Exists(proposedTrans.Event)) 00176 pDevice->WriteActuator(proposedTrans.Event); 00177 FD_DS_SYNC("DeviceExecutor::SyncEvents(): scheduled event: ok"); 00178 return proposedTrans.Event; 00179 } 00180 00181 // get and execute hardware events 00182 if(Idx sev=pDevice->ReadSensor()) { 00183 FD_DS_SYNC("DeviceExecutor::SyncEvents(): sensor event " << EStr(sev)); 00184 if(!ProposingExecutor::ExecuteEvent(sev)) { 00185 FD_DS_SYNC("DeviceExecutor::SyncEvents(): sync error: invalid sensor event"); 00186 mSyncError=true; 00187 pDevice->Reset(); 00188 return 0; 00189 } 00190 return sev; 00191 } 00192 00193 00194 FD_DS_SYNC("DeviceExecutor::SyncEvents(): no events ready"); 00195 return 0; 00196 00197 #endif 00198 } 00199 00200 //SyncWait() 00201 bool DeviceExecutor::SyncWait(tpTime::Type duration){ 00202 00203 // no plugin, no run 00204 #ifndef FAUDES_PLUGIN_IODEVICE 00205 return false; 00206 #else 00207 00208 // no device, no run 00209 if(!pDevice) return false; 00210 00211 // report 00212 FD_DS_SYNC("DeviceExecutor::SyncWait(): sleep " << tpTime::Str(duration) ); 00213 00214 // adjust 00215 const TimedEvent& proposedTrans=ProposeNextTransition(); 00216 if(proposedTrans.Time<duration) duration=proposedTrans.Time; 00217 if(duration <0) duration=0; 00218 00219 // report 00220 FD_DS_SYNC("DeviceExecutor::SyncWait(): adjusted by proposal: " << tpTime::Str(duration) ); 00221 00222 // doit 00223 bool res=pDevice->WaitSensors(duration); 00224 00225 // done 00226 return res; 00227 00228 #endif // io plugin 00229 } 00230 00231 00232 //SyncStep(duartion) 00233 Idx DeviceExecutor::SyncStep(tpTime::Type duration){ 00234 FD_DS_SYNC("DeviceExecutor::SyncStep("<< tpTime::Str(duration) << ")"); 00235 00236 // no plugin, no run 00237 #ifndef FAUDES_PLUGIN_IODEVICE 00238 return 0; 00239 #else 00240 00241 // no device, no run 00242 if(!pDevice) return 0; 00243 00244 // result 00245 Idx res=0; 00246 00247 // doit 00248 if(!SyncTime()) return res; 00249 if((res=SyncEvents())!=0) return res; 00250 if(!SyncWait(duration)) return res; 00251 if(!SyncTime()) return res; 00252 res=SyncEvents(); 00253 00254 // done 00255 return res; 00256 00257 #endif // io plugin 00258 } 00259 00260 //SyncRun(duartion) 00261 bool DeviceExecutor::SyncRun(tpTime::Type duration){ 00262 FD_DS_SYNC("DeviceExecutor::SyncRun("<< tpTime::Str(duration) << ")"); 00263 00264 // prepare 00265 tpTime::Type genNow=CurrentTime(); 00266 tpTime::Type genStop=genNow+duration; 00267 tpTime::Type genLeft=genStop-genNow; 00268 if(duration==tpTime::Max) { 00269 genStop=tpTime::Max; 00270 genLeft=tpTime::Max; 00271 } 00272 00273 // loop time 00274 while(genLeft>0) { 00275 // step 00276 if(SyncStep(genLeft)==0) return false; 00277 // update 00278 genNow=CurrentTime(); 00279 genLeft=genStop-genNow; 00280 if(duration==tpTime::Max) genLeft=tpTime::Max; 00281 } 00282 // done 00283 return true; 00284 } 00285 00286 } // namespace 00287