EzIO.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. using GSG.NET.Concurrent;
  2. using GSG.NET.Excel;
  3. using GSG.NET.Logging;
  4. using GSG.NET.Quartz;
  5. using GSG.NET.Utils;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Threading;
  10. using VehicleControlSystem.ControlLayer.Lib.EziPlusE;
  11. namespace VehicleControlSystem.ControlLayer.IO
  12. {
  13. public partial class EzIO : IIO, IDisposable
  14. {
  15. #region Bit Mask
  16. public readonly uint[] bitOnMask =
  17. {
  18. 0x00000001, 0x00000002, 0x00000004, 0x00000008,
  19. 0x00000010, 0x00000020, 0x00000040, 0x00000080,
  20. 0x00000100, 0x00000200, 0x00000400, 0x00000800,
  21. 0x00001000, 0x00002000, 0x00004000, 0x00008000,
  22. 0x00010000, 0x00020000, 0x00040000, 0x00080000,
  23. 0x00100000, 0x00200000, 0x00400000, 0x00800000,
  24. 0x01000000, 0x02000000, 0x04000000, 0x08000000,
  25. 0x10000000, 0x20000000, 0x40000000, 0x80000000
  26. };
  27. public readonly uint[] bitOffMask =
  28. {
  29. 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFB, 0xFFFFFFF7,
  30. 0xFFFFFFEF, 0xFFFFFFDF, 0xFFFFFFBF, 0xFFFFFF7F,
  31. 0xFFFFFEFF, 0xFFFFFDFF, 0xFFFFFBFF, 0xFFFFF7FF,
  32. 0xFFFFEFFF, 0xFFFFDFFF, 0xFFFFBFFF, 0xFFFF7FFF,
  33. 0xFFFEFFFF, 0xFFFDFFFF, 0xFFFBFFFF, 0xFFF7FFFF,
  34. 0xFFEFFFFF, 0xFFDFFFFF, 0xFFBFFFFF, 0xFF7FFFFF,
  35. 0xFEFFFFFF, 0xFDFFFFFF, 0xFBFFFFFF, 0xF7FFFFFF,
  36. 0xEFFFFFFF, 0xDFFFFFFF, 0xBFFFFFFF, 0x7FFFFFFF
  37. };
  38. public readonly uint[] servoAmpInputBitOnMask =
  39. {
  40. 0x04000000, 0x08000000, 0x10000000, 0x20000000,
  41. 0x40000000, 0x80000000, 0x00400000, 0x00800000,
  42. 0x01000000
  43. };
  44. public readonly uint[] servoAmpOutputBitMask =
  45. {
  46. 0x00008000, 0x00010000, 0x00020000, 0x00040000,
  47. 0x00080000, 0x00100000, 0x00200000, 0x00400000,
  48. 0x00800000
  49. };
  50. #endregion
  51. static Logger logger = Logger.GetLogger();
  52. bool IsThreadAlive = true;
  53. public List<EzBoard> BoardList = new List<EzBoard>();
  54. List<BitBlock> _inPutIOList = null;
  55. public List<BitBlock> InPutIOList
  56. {
  57. get => this._inPutIOList;
  58. }
  59. List<BitBlock> _outPutIOList = null;
  60. public List<BitBlock> OutPutIOList
  61. {
  62. get => this._outPutIOList;
  63. }
  64. UInt16[] _incomingBuffer;
  65. UInt16[] _outcomingBuffer;
  66. Thread _readThread;
  67. bool isConnectError = false;
  68. public bool IsConnectError
  69. {
  70. get => this.isConnectError;
  71. set
  72. {
  73. if ( this.isConnectError == value )
  74. return;
  75. this.isConnectError = value;
  76. if ( isConnectError )
  77. this.qQ.Enqueue( new QoDiconnected() {Arg0 = "EzIO" } );
  78. else
  79. this.qQ.Enqueue( new QoConnected() {Arg0 = "EzIO" } );
  80. }
  81. }
  82. TsMap<string, SyncObject> ddWaitChgBlock = new TsMap<string, SyncObject>();
  83. #region Pull Thread
  84. public TsQueue<QueueObject> qQ = new TsQueue<QueueObject>( 512 );
  85. public Thread pullThread;
  86. #endregion
  87. #region public Method
  88. public int GetBit( uint usIOAddr, bool pbval )
  89. {
  90. throw new NotImplementedException();
  91. }
  92. public int GetBit( string strIOAddr, bool pbVal )
  93. {
  94. throw new NotImplementedException();
  95. }
  96. public int GetByte( uint usIOAddr, byte pcValue )
  97. {
  98. throw new NotImplementedException();
  99. }
  100. public int GetByte( string strIOAddr, byte pcValue )
  101. {
  102. throw new NotImplementedException();
  103. }
  104. public int GetWord( uint usIOAddr, short pwValue )
  105. {
  106. throw new NotImplementedException();
  107. }
  108. public int GetWord( string strIOAddr, short pwValue )
  109. {
  110. throw new NotImplementedException();
  111. }
  112. public int Initialize( List<EzBoard> ezBoards )
  113. {
  114. this.BoardList = ezBoards;
  115. this._incomingBuffer = new ushort[ezBoards.Count];
  116. this._outcomingBuffer = new ushort[ezBoards.Count];
  117. this.IsThreadAlive = true;
  118. _readThread = new Thread( this.IOThread );
  119. this._readThread.IsBackground = true;
  120. this._readThread.Start();
  121. return 0;
  122. }
  123. #endregion
  124. public bool IsDeviceOpened()
  125. {
  126. throw new NotImplementedException();
  127. }
  128. public bool IsOff( uint usIOAddr )
  129. {
  130. throw new NotImplementedException();
  131. }
  132. public bool IsOff( string ioTag, bool isInput = true )
  133. {
  134. BitBlock bit = null;
  135. if ( isInput )
  136. bit = this._inPutIOList.Where( x => ioTag.Equals( x.Tag ) ).FirstOrDefault();
  137. else
  138. bit = this._outPutIOList.Where( x => ioTag.Equals( x.Tag ) ).FirstOrDefault();
  139. return !bit.IsBitOn;
  140. }
  141. public bool IsOn( uint usIOAddr )
  142. {
  143. throw new NotImplementedException();
  144. }
  145. //public int IsOn( string strIOAddr, bool pbVal )
  146. //{
  147. // var io = this._inPutIOList.Where( x => strIOAddr.Equals( x.Tag ) ).FirstOrDefault();
  148. // if( io == null )
  149. // return -1;
  150. // else
  151. // {
  152. // }
  153. // return 0;
  154. //}
  155. public bool IsOn( string ioTag, bool isInput = true )
  156. {
  157. BitBlock bit = null;
  158. if ( isInput )
  159. bit = this._inPutIOList.Where( x => ioTag.Equals( x.Tag ) ).FirstOrDefault();
  160. else
  161. bit = this._outPutIOList.Where( x => ioTag.Equals( x.Tag ) ).FirstOrDefault();
  162. return bit.IsBitOn;
  163. }
  164. public bool WaitChangeInputIO( bool exp, int timeout, string tag )
  165. {
  166. if ( exp == IsOn( tag ) )
  167. return true;
  168. Assert.IsFalse( ddWaitChgBlock.ContainsKey( tag ), "WaitChg InputIO already waiting:{0}", tag );
  169. try
  170. {
  171. var so = new SyncObject { };
  172. ddWaitChgBlock.Add( tag, so );
  173. so.Lock();
  174. return so.Await( timeout );
  175. }
  176. finally
  177. {
  178. this.ddWaitChgBlock.Remove( tag );
  179. }
  180. }
  181. public int LoadIOMap( string strFileName )
  182. {
  183. var bl = new ExcelMapper( strFileName ).Fetch<EzBoard>( "BOARD" ).ToList();
  184. this.BoardList = bl;
  185. var il = new ExcelMapper( strFileName ).Fetch<BitBlock>( "IN_IO" ).ToList();
  186. var inputIO = il.Where( x => !string.IsNullOrEmpty( x.Tag ) ).ToList();
  187. this._inPutIOList = inputIO;
  188. var ol = new ExcelMapper( strFileName ).Fetch<BitBlock>( "OUT_IO" ).ToList();
  189. var outputIO = ol.Where( x => !string.IsNullOrEmpty( x.Tag ) ).ToList();
  190. this._outPutIOList = outputIO;
  191. return 0;
  192. }
  193. public int OutputOff( uint usIOAddr )
  194. {
  195. throw new NotImplementedException();
  196. }
  197. public int OutputOff( string strIOAddr )
  198. {
  199. int result = 0;
  200. var outIO = this._outPutIOList.Where( x => strIOAddr.Equals( x.Tag ) ).FirstOrDefault();
  201. var boardType = this.BoardList.Where( x => x.BoardID == outIO.BoardNo ).FirstOrDefault().Type;
  202. uint bitMask = 0;
  203. if ( boardType == E_EzboardType.Servo )
  204. {
  205. bitMask = this.servoAmpOutputBitMask[outIO.Index];
  206. result = EziMOTIONPlusELib.FAS_SetIOOutput( outIO.BoardNo, 0, bitMask );
  207. }
  208. else
  209. {
  210. bitMask = bitOnMask[outIO.Index];
  211. result = EziMOTIONPlusELib.FAS_SetOutput( outIO.BoardNo, 0, bitMask );
  212. }
  213. return result;
  214. }
  215. public int OutputOn( uint usIOAddr )
  216. {
  217. //var outIO = this._inPutIOList.Where( x => strIOAddr.Equals( x.Tag ) ).FirstOrDefault();
  218. //EziMOTIONPlusELib.FAS_SetIOOutput( boardNo, writeMask, 0 );
  219. return 0;
  220. }
  221. public int OutputOn( string outputTag )
  222. {
  223. int result = 0;
  224. var outIO = this._outPutIOList.Where( x => outputTag.Equals( x.Tag ) ).FirstOrDefault();
  225. var boardType = this.BoardList.Where( x => x.BoardID == outIO.BoardNo ).FirstOrDefault().Type;
  226. uint bitMask = 0;
  227. if ( boardType == E_EzboardType.Servo )
  228. {
  229. bitMask = this.servoAmpOutputBitMask[outIO.Index];
  230. result = EziMOTIONPlusELib.FAS_SetIOOutput( outIO.BoardNo, bitMask, 0 );
  231. }
  232. else
  233. {
  234. bitMask = bitOnMask[outIO.Index];
  235. result = EziMOTIONPlusELib.FAS_SetOutput( outIO.BoardNo, bitMask, 0 );
  236. }
  237. return result;
  238. }
  239. #region 일정시간 이후 동작 구현
  240. void WriteOutputOn( string outputTag )
  241. {
  242. int result = 0;
  243. var outIO = this._outPutIOList.Where( x => outputTag.Equals( x.Tag ) ).FirstOrDefault();
  244. var boardType = this.BoardList.Where( x => x.BoardID == outIO.BoardNo ).FirstOrDefault().Type;
  245. uint bitMask = 0;
  246. if ( boardType == E_EzboardType.Servo )
  247. {
  248. bitMask = this.servoAmpOutputBitMask[outIO.Index];
  249. result = EziMOTIONPlusELib.FAS_SetIOOutput( outIO.BoardNo, bitMask, 0 );
  250. }
  251. else
  252. {
  253. bitMask = bitOnMask[outIO.Index];
  254. result = EziMOTIONPlusELib.FAS_SetOutput( outIO.BoardNo, bitMask, 0 );
  255. }
  256. }
  257. void WriteOutputOff( string strIOAddr )
  258. {
  259. int result = 0;
  260. var outIO = this._outPutIOList.Where( x => strIOAddr.Equals( x.Tag ) ).FirstOrDefault();
  261. var boardType = this.BoardList.Where( x => x.BoardID == outIO.BoardNo ).FirstOrDefault().Type;
  262. uint bitMask = 0;
  263. if ( boardType == E_EzboardType.Servo )
  264. {
  265. bitMask = this.servoAmpOutputBitMask[outIO.Index];
  266. result = EziMOTIONPlusELib.FAS_SetIOOutput( outIO.BoardNo, 0, bitMask );
  267. }
  268. else
  269. {
  270. bitMask = bitOnMask[outIO.Index];
  271. result = EziMOTIONPlusELib.FAS_SetOutput( outIO.BoardNo, 0, bitMask );
  272. }
  273. }
  274. public void WriteOutputIO( string tag, bool on, int after = 0 )
  275. {
  276. if ( on )
  277. {
  278. if ( after > 0 )
  279. TimerUtils.Once( after, WriteOutputOn, tag );
  280. else
  281. WriteOutputOn( tag );
  282. }
  283. else
  284. {
  285. if ( after > 0 )
  286. TimerUtils.Once( after, WriteOutputOff, tag );
  287. else
  288. WriteOutputOff( tag );
  289. }
  290. }
  291. #endregion
  292. public int OutputToggle( uint usIOAddr )
  293. {
  294. throw new NotImplementedException();
  295. }
  296. public int OutputToggle( string strIOAddr )
  297. {
  298. throw new NotImplementedException();
  299. }
  300. public int PutByte( uint usIOAddr, byte pcValue )
  301. {
  302. throw new NotImplementedException();
  303. }
  304. public int PutByte( string strIOAddr, byte pcValue )
  305. {
  306. throw new NotImplementedException();
  307. }
  308. public int PutWord( uint usIOAddr, short pwValue )
  309. {
  310. throw new NotImplementedException();
  311. }
  312. public int PutWord( string strIOAddr, short pwValue )
  313. {
  314. throw new NotImplementedException();
  315. }
  316. #region Thread
  317. public void RunIOThread()
  318. {
  319. try
  320. {
  321. ThreadStart();
  322. }
  323. catch ( Exception )
  324. {
  325. }
  326. finally
  327. {
  328. }
  329. }
  330. public void ThreadStart()
  331. {
  332. this.IsThreadAlive = true;
  333. this._readThread = ThreadUtils.Invoke( IOThread );
  334. this.pullThread = ThreadUtils.Invoke( PullQueueThread );
  335. }
  336. void IOThread()
  337. {
  338. var sTime = SwUtils.CurrentTimeMillis;
  339. while ( IsThreadAlive )
  340. {
  341. Thread.Sleep( 5 );
  342. try
  343. {
  344. if ( !IsConnetedAllBoard() )
  345. {
  346. if ( !ConnectAllBoard() )
  347. {
  348. IsConnectError = true;
  349. }
  350. Thread.Sleep( 1000 );
  351. continue;
  352. }
  353. IsConnectError = false;
  354. ReadBoardIO();
  355. //Console.WriteLine( $"Read Time - { SwUtils.Elapsed( sTime ) } mm" );
  356. //sTime = SwUtils.CurrentTimeMillis;
  357. }
  358. catch ( Exception ex )
  359. {
  360. logger.E( $"Exception [EzIO IORead Thread] - {ex.StackTrace}" );
  361. }
  362. }
  363. logger.D( "[EzIO] - Dispose" );
  364. }
  365. void ReadBoardIO()
  366. {
  367. foreach ( var board in this.BoardList )
  368. {
  369. if ( !IsConnetedBoard( board.BoardID ) )
  370. continue;
  371. switch ( board.Type )
  372. {
  373. case E_EzboardType.Servo:
  374. {
  375. uint axisDIn = 0, axisDOut = 0, axisStatus = 0;
  376. int cmdPos = 0, actPos = 0, posErr = 0, actVel = 0;
  377. ushort posItemNo = 0;
  378. if ( EziMOTIONPlusELib.FAS_GetAllStatus( board.BoardID, ref axisDIn, ref axisDOut, ref axisStatus,
  379. ref cmdPos, ref actPos, ref posErr, ref actVel, ref posItemNo ) == EziMOTIONPlusELib.FMM_OK )
  380. {
  381. //if ( this._inPutIOList.Where( x => x.BoardNo == board.BoardID ).Count() <= 0 ) break;
  382. var input = this._inPutIOList.Where( x => x.BoardNo == board.BoardID ).ToList();
  383. input.ForEach( i =>
  384. {
  385. var isOn = Convert.ToBoolean( axisDIn & this.servoAmpInputBitOnMask[i.Index] ) ? true : false;
  386. if ( i.IsBitOn != isOn )
  387. i.IsChanged = true;
  388. i.IsBitOn = isOn;
  389. } );
  390. var output = this._outPutIOList.Where( x => x.BoardNo == board.BoardID ).ToList();
  391. output.ForEach( o =>
  392. {
  393. var isOn = Convert.ToBoolean( axisDOut & this.servoAmpOutputBitMask[o.Index] ) ? true : false;
  394. if ( o.IsBitOn != isOn )
  395. o.IsChanged = true;
  396. o.IsBitOn = isOn;
  397. } );
  398. }
  399. }
  400. break;
  401. case E_EzboardType.IOInput:
  402. {
  403. uint inValue = 0, latchValue = 0;
  404. int result = EziMOTIONPlusELib.FMM_OK;
  405. result = EziMOTIONPlusELib.FAS_GetInput( board.BoardID, ref inValue, ref latchValue );
  406. if ( result == EziMOTIONPlusELib.FMM_OK )
  407. {
  408. var input = this._inPutIOList.Where( x => x.BoardNo == board.BoardID ).ToList();
  409. input.ForEach( i =>
  410. {
  411. var isOn = Convert.ToBoolean( inValue & this.bitOnMask[i.Index] ) ? true : false;
  412. if ( i.IsBitOn != isOn )
  413. i.IsChanged = true;
  414. i.IsBitOn = isOn;
  415. } );
  416. }
  417. else
  418. logger.E( $"EzIO - [{board.BoardID}] Read Fail Error Code {result}" );
  419. }
  420. break;
  421. case E_EzboardType.IOOutput:
  422. {
  423. uint outValue = 0, outStatus = 0;
  424. int result = EziMOTIONPlusELib.FMM_OK;
  425. result = EziMOTIONPlusELib.FAS_GetOutput( board.BoardID, ref outValue, ref outStatus );
  426. if ( result == EziMOTIONPlusELib.FMM_OK )
  427. {
  428. var output = this._outPutIOList.Where( x => x.BoardNo == board.BoardID ).ToList();
  429. output.ForEach( o =>
  430. {
  431. var isOn = Convert.ToBoolean( outValue & this.bitOnMask[o.Index] ) ? true : false;
  432. if ( o.IsBitOn != isOn )
  433. o.IsChanged = true;
  434. o.IsBitOn = isOn;
  435. } );
  436. }
  437. else
  438. logger.E( $"EzIO - [{board.BoardID}] Read Fail Error Code {result}" );
  439. }
  440. break;
  441. default:
  442. break;
  443. }
  444. }
  445. FireChangedIO();
  446. }
  447. void FireChangedIO()
  448. {
  449. this.InPutIOList.ForEach( i =>
  450. {
  451. if ( i.IsChanged )
  452. {
  453. i.IsChanged = false;
  454. var clone = ObjectCopyUtils.DeepClone<BitBlock>( i );
  455. this.qQ.Enqueue( new QoChangedIO { Arg0 = clone } );
  456. NotifySyncBit( clone );
  457. }
  458. } );
  459. this.OutPutIOList.ForEach( o =>
  460. {
  461. if ( o.IsChanged )
  462. {
  463. o.IsChanged = false;
  464. var clone = ObjectCopyUtils.DeepClone<BitBlock>( o );
  465. this.qQ.Enqueue( new QoChangedIO { Arg0 = clone } );
  466. }
  467. } );
  468. }
  469. void PullQueueThread()
  470. {
  471. while ( IsThreadAlive )
  472. {
  473. try
  474. {
  475. var o = qQ.Dequeue();
  476. if ( o is QoConnected )
  477. DelegateUtils.Invoke( OnContd, o.Arg0 );
  478. else if ( o is QoDiconnected )
  479. DelegateUtils.Invoke( OnDiscontd, o.Arg0 );
  480. else if ( o is QoChangedIO )
  481. DelegateUtils.Invoke( OnChangedIO, o.Arg0 );
  482. else if ( o is QoWriteIO )
  483. DelegateUtils.Invoke( OnWriteIO, o.Arg0 );
  484. else if ( o is QoLog )
  485. DelegateUtils.Invoke( OnLog, o.Arg0, o.Arg1 );
  486. else
  487. Assert.Fail( "Unk Object {0}", o );
  488. }
  489. catch ( ThreadAbortException )
  490. {
  491. }
  492. catch ( Exception e )
  493. {
  494. logger.E( e );
  495. }
  496. }
  497. logger.D( "[EzIO] - PullQueue Thread Dispose" );
  498. }
  499. #endregion
  500. /// <summary>
  501. /// InputIO 변경 알림
  502. /// </summary>
  503. /// <param name="block"></param>
  504. void NotifySyncBit( BitBlock block )
  505. {
  506. if ( ddWaitChgBlock.ContainsKey( block.Tag ) )
  507. {
  508. var so = ddWaitChgBlock[block.Tag];
  509. so.Expect = block;
  510. so.Notify();
  511. }
  512. }
  513. bool IsConnetedBoard( int boardNo )
  514. {
  515. return EziMOTIONPlusELib.FAS_IsSlaveExist( boardNo ) == 1;
  516. }
  517. bool IsConnetedAllBoard()
  518. {
  519. foreach ( var b in this.BoardList )
  520. {
  521. if ( !IsConnetedBoard( b.BoardID ) )
  522. {
  523. this.qQ.Clear();//연결이 끊어지면 내용을 삭제.
  524. return false;
  525. }
  526. }
  527. return true;
  528. }
  529. bool ConnectAllBoard()
  530. {
  531. foreach ( var b in this.BoardList )
  532. {
  533. if ( IsConnetedBoard( b.BoardID ) )
  534. continue;
  535. var addr = b.IPAddress.Split( '.' );
  536. byte boardNo = Convert.ToByte( addr[3] );
  537. if ( EziMOTIONPlusELib.FAS_Connect( (byte)192, (byte)168, (byte)0, boardNo, b.BoardID ) != EziMOTIONPlusELib.FMM_OK )
  538. {
  539. logger.E( $"EzIO - Connect Fail {b.BoardID}" );
  540. return false;
  541. }
  542. }
  543. return true;
  544. }
  545. public int Terminate()
  546. {
  547. this.IsThreadAlive = false;
  548. if ( this._readThread != null && this._readThread.IsAlive )
  549. {
  550. if ( !this._readThread.Join( 3000 ) )
  551. this._readThread.Abort();
  552. }
  553. this.BoardList.ForEach( b =>
  554. {
  555. EziMOTIONPlusELib.FAS_Close( b.BoardID );
  556. } );
  557. return 0;
  558. }
  559. public int Initialize()
  560. {
  561. throw new NotImplementedException();
  562. }
  563. int GetModuleAndBitNoByAddress( uint usIOAddr, out int boardNo, out int bitNo )
  564. {
  565. long nOffset = 0;
  566. long nCount = 0;
  567. long nAddress = usIOAddr;
  568. int INPUT_ORIGIN = 1000;
  569. int OUTPUT_ORIGIN = 2000;
  570. boardNo = 0;
  571. bitNo = 0;
  572. if ( usIOAddr < OUTPUT_ORIGIN )
  573. {
  574. nOffset = usIOAddr - INPUT_ORIGIN;
  575. for ( int nModNo = 0; nModNo < this.BoardList.Count; nModNo++ )
  576. {
  577. // Get Input CH Count Using Module ID
  578. //AxdInfoGetInputCount( nModNo, nCount );
  579. if ( nOffset - nCount < 0 )
  580. {
  581. boardNo = nModNo;
  582. bitNo = (int)nOffset;
  583. return 0;
  584. }
  585. nOffset -= nCount;
  586. }
  587. }
  588. else
  589. {
  590. nOffset = usIOAddr - OUTPUT_ORIGIN;
  591. for ( int nModNo = 0; nModNo < this.BoardList.Count; nModNo++ )
  592. {
  593. // Get Output CH Count Using Module ID
  594. //AxdInfoGetOutputCount( nModNo, nCount );
  595. if ( nOffset - nCount < 0 )
  596. {
  597. boardNo = nModNo;
  598. bitNo = (int)nOffset;
  599. return 0;
  600. }
  601. nOffset -= nCount;
  602. }
  603. }
  604. return 0;
  605. }
  606. #region IDisposable Support
  607. private bool disposedValue = false; // 중복 호출을 검색하려면
  608. protected virtual void Dispose( bool disposing )
  609. {
  610. if ( !disposedValue )
  611. {
  612. if ( disposing )
  613. {
  614. // TODO: 관리되는 상태(관리되는 개체)를 삭제합니다.
  615. if ( this.pullThread != null )
  616. {
  617. this.IsThreadAlive = false;
  618. if ( !this.pullThread.Join( 2000 ) && this.pullThread.IsAlive )
  619. {
  620. this.pullThread.Abort();
  621. }
  622. this.pullThread = null;
  623. }
  624. ThreadUtils.Kill( this.pullThread );
  625. Terminate(); //Board Close
  626. }
  627. // TODO: 관리되지 않는 리소스(관리되지 않는 개체)를 해제하고 아래의 종료자를 재정의합니다.
  628. // TODO: 큰 필드를 null로 설정합니다.
  629. disposedValue = true;
  630. }
  631. }
  632. // TODO: 위의 Dispose(bool disposing)에 관리되지 않는 리소스를 해제하는 코드가 포함되어 있는 경우에만 종료자를 재정의합니다.
  633. // ~EzIO()
  634. // {
  635. // // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요.
  636. // Dispose(false);
  637. // }
  638. // 삭제 가능한 패턴을 올바르게 구현하기 위해 추가된 코드입니다.
  639. public void Dispose()
  640. {
  641. // 이 코드를 변경하지 마세요. 위의 Dispose(bool disposing)에 정리 코드를 입력하세요.
  642. Dispose( true );
  643. // TODO: 위의 종료자가 재정의된 경우 다음 코드 줄의 주석 처리를 제거합니다.
  644. // GC.SuppressFinalize(this);
  645. }
  646. #endregion
  647. }
  648. }