Barst  2.0
A server that controls lab hardware.
cpl ft io.cpp
1 #include "cpl defs.h"
2 #include "ftdi device.h"
3 
4 
11 CMultiWPeriph::CMultiWPeriph(const SValveInit &sValveInit, CComm *pcComm, const SInitPeriphFT &sInitFT,
12  int &nError, HANDLE hNewData, CTimer* pcTimer) : CPeriphFTDI(MULTI_W_P, sInitFT), m_sInit(sValveInit),
13  m_abData(sValveInit.dwBoards*8, false), m_ucDefault(1<<sValveInit.ucLatch), m_ucMask(~(1<<sValveInit.ucLatch|
14  1<<sValveInit.ucClk|1<<sValveInit.ucData)), m_allIds(hNewData)
15 {
16  nError= 0;
17  m_bError= true;
18  m_pcMemPool= new CMemPool;
19  m_pcMemRing = NULL;
20  InitializeCriticalSection(&m_hDataSafe);
21  // minw has to be at least as large as required for writing full boards, dwbuff also has to be as large, but can be larger
22  // e.g. if adc device is also active this dwBuff will be larger than dwMinSizeW
23  if (!pcComm || sInitFT.dwMinSizeW < (sValveInit.dwBoards*8*2+2)*sValveInit.dwClkPerData ||
24  sInitFT.dwBuff < sInitFT.dwMinSizeW || !sValveInit.dwClkPerData || !sValveInit.dwBoards || !pcTimer ||
25  !hNewData)
26  {
27  nError= BAD_INPUT_PARAMS;
28  return;
29  }
30  m_pcComm= pcComm;
31  m_pcTimer= pcTimer;
32  m_bUpdated= false;
33  m_bChanged= false;
34  m_nProcessed= 0;
35  m_bError= false;
36  m_eState= eInactivateState;
37  m_hNext= hNewData; // you set this when new data is availible to make channel go
38 }
39 
40 DWORD CMultiWPeriph::GetInfo(void* pHead, DWORD dwSize)
41 {
42  if (!pHead)
43  return sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SValveInit)+sizeof(SInitPeriphFT);
44  if (dwSize<sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SValveInit)+sizeof(SInitPeriphFT))
45  return 0;
46 
47  ((SBaseOut*)pHead)->sBaseIn.dwSize= sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SValveInit)+sizeof(SInitPeriphFT);
48  ((SBaseOut*)pHead)->sBaseIn.eType= eResponseEx;
49  ((SBaseOut*)pHead)->sBaseIn.nChan= m_sInitFT.nChan;
50  ((SBaseOut*)pHead)->sBaseIn.nError= 0;
51  ((SBaseOut*)pHead)->bActive= GetState() == eActive;
52  _tcsncpy_s(((SBaseOut*)pHead)->szName, DEVICE_NAME_SIZE, m_csName.c_str(), _TRUNCATE);
53  pHead= (char*)pHead+ sizeof(SBaseOut);
54 
55  ((SBase*)pHead)->dwSize= sizeof(SInitPeriphFT)+sizeof(SBase);
56  ((SBase*)pHead)->eType= eFTDIPeriphInit;
57  pHead= (char*)pHead+ sizeof(SBase);
58  memcpy(pHead, &m_sInitFT, sizeof(SInitPeriphFT));
59  pHead= (char*)pHead+ sizeof(SInitPeriphFT);
60 
61  ((SBase*)pHead)->dwSize= sizeof(SValveInit)+sizeof(SBase);
62  ((SBase*)pHead)->eType= eFTDIMultiWriteInit;
63  pHead= (char*)pHead+ sizeof(SBase);
64  memcpy(pHead, &m_sInit, sizeof(SValveInit));
65 
66  return sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SValveInit)+sizeof(SInitPeriphFT);
67 }
68 
69 CMultiWPeriph::~CMultiWPeriph()
70 {
71  DeleteCriticalSection(&m_hDataSafe);
72  delete m_pcMemPool;
73 }
74 
75 bool CMultiWPeriph::DoWork(void *pHead, DWORD dwSize, FT_HANDLE ftHandle, EStateFTDI eReason, int nError)
76 {
77  if (m_bError)
78  return true;
79  unsigned char *aucBuff= (unsigned char *)pHead;
80  bool bNotEmpty;
81 
82  if (eReason == eActivateState || eReason == eInactivateState) // update state
83  {
84  EnterCriticalSection(&m_hDataSafe);
85  m_eState= eReason == eActivateState?eActive:eInactivateState;
86  LeaveCriticalSection(&m_hDataSafe);
87  } else if (eReason == eRecover)
88  {
89  EnterCriticalSection(&m_hDataSafe);
90  if (m_eState == eActive || m_eState == eInactivateState)
91  {
92  m_bUpdated= true; // clock out last data again
93  SetEvent(m_hNext);
94  }
95  LeaveCriticalSection(&m_hDataSafe);
96  }
97 
98  if (m_eState == eInactivateState && eReason == ePreWrite) // shut it down
99  {
100  EnterCriticalSection(&m_hDataSafe);
101  m_eState= eInactive;
102  m_bUpdated= false;
103  LeaveCriticalSection(&m_hDataSafe);
104  ResetEvent(m_hNext);
105  // no new requests can be added because state is inactive
106  while (m_allIds.GetSize()) // respond to all waiting users
107  {
108  SData sData;
109  sData.dwSize= sizeof(SBaseIn);
110  sData.pDevice= this;
111  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseIn));
112  if (sData.pHead)
113  {
114  ((SBaseIn*)sData.pHead)->eType= eResponse;
115  ((SBaseIn*)sData.pHead)->nChan= m_sInitFT.nChan;
116  ((SBaseIn*)sData.pHead)->nError= DEVICE_CLOSING;
117  ((SBaseIn*)sData.pHead)->dwSize= sizeof(SBaseIn);
118  m_pcComm->SendData(&sData, m_allIds.Front(true, bNotEmpty));
119  }
120  }
121  m_nProcessed= 0;
122  m_bChanged= false;
123  // write full buffer length (even more than dwMinSizeW)
124  for (DWORD i= 0; i<m_sInitFT.dwBuff;++i) // now set these pins to default
125  aucBuff[i]= (aucBuff[i]&m_ucMask)|m_ucDefault;
126  } else if (m_eState == eActive && eReason == ePreWrite) // write the next set of data
127  {
128  EnterCriticalSection(&m_hDataSafe);
129  if (m_bUpdated)
130  {
131  int k= 0;
132  DWORD i= 0;
133  for (;i<m_sInit.dwBoards*8*2*m_sInit.dwClkPerData;)
134  {
135  // count number of boards from closest to computer to furthest, bytes that are written first control furthest board
136  // so write last board at the start of the buffer and the first board at end of the buffer.
137  for (DWORD j= 0; j<m_sInit.dwClkPerData; ++j)
138  aucBuff[i++]= (aucBuff[i]&m_ucMask)|(m_abData[(m_sInit.dwBoards-1-k/8)*8+k%8]?1<<m_sInit.ucData:0)|1<<m_sInit.ucClk;
139  for (DWORD j= 0; j<m_sInit.dwClkPerData; ++j)
140  aucBuff[i++]= (aucBuff[i]&m_ucMask)|(m_abData[(m_sInit.dwBoards-1-k/8)*8+k%8]?1<<m_sInit.ucData:0);
141  ++k;
142  }
143  for (DWORD j= 0; j<m_sInit.dwClkPerData; ++j)
144  aucBuff[i]= aucBuff[i++]&m_ucMask;
145  for (DWORD j= 0; j<m_sInit.dwClkPerData; ++j)
146  aucBuff[i]= (aucBuff[i++]&m_ucMask)|1<<m_sInit.ucLatch;
147  m_bUpdated= false; // done updating
148  m_bChanged= true;
149  m_nProcessed= m_allIds.GetSize(); // current number of updates proccesed
150  m_dInitial= g_cTimer.Seconds(); // time right before writing
151  ResetEvent(m_hNext);
152  }
153  LeaveCriticalSection(&m_hDataSafe);
154  } else if (m_eState == eActive && eReason == ePostWrite) // now let user know if succesful and set buffer to default.
155  {
156  if (m_bChanged)
157  {
158  for (int i= 0; i<m_nProcessed; ++i)
159  {
160  SData sData;
161  sData.dwSize= sizeof(SBaseOut);
162  sData.pDevice= this;
163  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseOut));
164  if (sData.pHead)
165  {
166  ((SBaseOut*)sData.pHead)->sBaseIn.eType= eResponseExD;
167  ((SBaseOut*)sData.pHead)->sBaseIn.nChan= m_sInitFT.nChan;
168  ((SBaseOut*)sData.pHead)->sBaseIn.nError= nError;
169  ((SBaseOut*)sData.pHead)->sBaseIn.dwSize= sizeof(SBaseOut);
170  ((SBaseOut*)sData.pHead)->dDouble= m_dInitial;
171  m_pcComm->SendData(&sData, m_allIds.Front(true, bNotEmpty));
172  }
173  }
174  m_nProcessed= 0;
175  for (DWORD i= 0; i<(m_sInit.dwBoards*8*2+2)*m_sInit.dwClkPerData;++i)
176  aucBuff[i]= (aucBuff[i]&m_ucMask)|m_ucDefault;
177  m_bChanged= false;
178  }
179  }
180  return true;
181 }
182 
183 EStateFTDI CMultiWPeriph::GetState()
184 {
185  EnterCriticalSection(&m_hDataSafe);
186  EStateFTDI eState= m_eState;
187  LeaveCriticalSection(&m_hDataSafe);
188  return eState;
189 }
190 
191 void CMultiWPeriph::ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
192 {
193  if(m_bError)
194  return;
195  if (!pHead || dwSize <= sizeof(SBaseIn)+sizeof(SBase) || ((SBaseIn*)pHead)->eType != eData
196  || ((SBase*)((char*)pHead+sizeof(SBaseIn)))->eType != eFTDIMultiWriteData ||
197  ((SBaseIn*)pHead)->dwSize != dwSize || (dwSize-sizeof(SBaseIn)-sizeof(SBase))%sizeof(SValveData)) // there has to be at least some data
198  {
199  SData sData;
200  sData.dwSize= sizeof(SBaseIn);
201  sData.pDevice= this;
202  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseIn));
203  if (sData.pHead)
204  {
205  ((SBaseIn*)sData.pHead)->dwSize= sizeof(SBaseIn);
206  ((SBaseIn*)sData.pHead)->eType= eResponse;
207  ((SBaseIn*)sData.pHead)->nChan= m_sInitFT.nChan;
208  ((SBaseIn*)sData.pHead)->nError= INVALID_COMMAND;
209  m_pcComm->SendData(&sData, llId);
210  }
211  return;
212  }
213 
214  SValveData *asValveData= (SValveData*)((char*)pHead + sizeof(SBaseIn) + sizeof(SBase));
215  int nError= 0;
216  EnterCriticalSection(&m_hDataSafe);
217  if (m_eState == eActive)
218  {
219  for (DWORD i= 0; i<(dwSize-sizeof(SBaseIn)-sizeof(SBase))/sizeof(SValveData); ++i)
220  {
221  if (asValveData[i].usIndex<m_abData.size())
222  m_abData[asValveData[i].usIndex]= asValveData[i].bValue;
223  else
224  nError= BAD_INPUT_PARAMS;
225  }
226  if (!nError)
227  {
228  m_bUpdated= true;
229  m_allIds.Push(llId); // pipe to notify of success
230  SetEvent(m_hNext); // update only in cc
231  }
232  } else
233  nError= INACTIVE_DEVICE;
234  LeaveCriticalSection(&m_hDataSafe);
235 
236  if (nError)
237  {
238  SData sData;
239  sData.dwSize= sizeof(SBaseIn);
240  sData.pDevice= this;
241  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseIn));
242  if (sData.pHead)
243  {
244  ((SBaseIn*)sData.pHead)->dwSize= sizeof(SBaseIn);
245  ((SBaseIn*)sData.pHead)->eType= eResponse;
246  ((SBaseIn*)sData.pHead)->nChan= m_sInitFT.nChan;
247  ((SBaseIn*)sData.pHead)->nError= nError;
248  m_pcComm->SendData(&sData, llId);
249  }
250  }
251 }
252 
253 
254 
255 CMultiRPeriph::CMultiRPeriph(const SValveInit &sValveInit, CComm *pcComm, const SInitPeriphFT &sInitFT,
256  int &nError, HANDLE hNewData, CTimer* pcTimer) : CPeriphFTDI(MULTI_R_P, sInitFT), m_sInit(sValveInit),
257  m_ucDefault(1<<sValveInit.ucLatch|1<<sValveInit.ucClk), m_ucMask(~(1<<sValveInit.ucLatch|
258  1<<sValveInit.ucClk|1<<sValveInit.ucData))
259 {
260  nError= 0;
261  m_bError= true;
262  m_pcMemRing = NULL;
263  InitializeCriticalSection(&m_hDataSafe);
264  m_pcMemPool= new CMemPool;
265  // minw has to be at least as large as required for writing full boards, dwbuff also has to be as large
266  if (!pcComm || sInitFT.dwMinSizeW < (sValveInit.dwBoards*8*2+2+4)*sValveInit.dwClkPerData ||
267  m_sInitFT.dwBuff < sInitFT.dwMinSizeW || sInitFT.dwMinSizeW != sInitFT.dwMinSizeR ||
268  !sValveInit.dwClkPerData || !sValveInit.dwBoards || !pcTimer || !hNewData)
269  {
270  nError= BAD_INPUT_PARAMS;
271  return;
272  }
273  m_pcComm= pcComm;
274  m_pcTimer= pcTimer;
275  m_bRead= false;
276  m_nProcessed= 0;
277  m_bError= false;
278  m_eState= eInactivateState;
279  m_hNext= hNewData; // you set this when new data is availible
280 }
281 
282 DWORD CMultiRPeriph::GetInfo(void* pHead, DWORD dwSize)
283 {
284  if (!pHead)
285  return sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SValveInit)+sizeof(SInitPeriphFT);
286  if (dwSize<sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SValveInit)+sizeof(SInitPeriphFT))
287  return 0;
288 
289  ((SBaseOut*)pHead)->sBaseIn.dwSize= sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SValveInit)+sizeof(SInitPeriphFT);
290  ((SBaseOut*)pHead)->sBaseIn.eType= eResponseEx;
291  ((SBaseOut*)pHead)->sBaseIn.nChan= m_sInitFT.nChan;
292  ((SBaseOut*)pHead)->sBaseIn.nError= 0;
293  ((SBaseOut*)pHead)->bActive= GetState() == eActive;
294  _tcsncpy_s(((SBaseOut*)pHead)->szName, DEVICE_NAME_SIZE, m_csName.c_str(), _TRUNCATE);
295  pHead= (char*)pHead+ sizeof(SBaseOut);
296 
297  ((SBase*)pHead)->dwSize= sizeof(SInitPeriphFT)+sizeof(SBase);
298  ((SBase*)pHead)->eType= eFTDIPeriphInit;
299  pHead= (char*)pHead+ sizeof(SBase);
300  memcpy(pHead, &m_sInitFT, sizeof(SInitPeriphFT));
301  pHead= (char*)pHead+ sizeof(SInitPeriphFT);
302 
303  ((SBase*)pHead)->dwSize= sizeof(SValveInit)+sizeof(SBase);
304  ((SBase*)pHead)->eType= eFTDIMultiReadInit;
305  pHead= (char*)pHead+ sizeof(SBase);
306  memcpy(pHead, &m_sInit, sizeof(SValveInit));
307 
308  return sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SValveInit)+sizeof(SInitPeriphFT);
309 }
310 
311 CMultiRPeriph::~CMultiRPeriph()
312 {
313  DeleteCriticalSection(&m_hDataSafe);
314  delete m_pcMemPool;
315 }
316 
317 bool CMultiRPeriph::DoWork(void *pHead, DWORD dwSize, FT_HANDLE ftHandle, EStateFTDI eReason, int nError)
318 {
319  if (m_bError)
320  return true;
321  unsigned char *aucBuff= (unsigned char *)pHead;
322 
323  if (eReason == eActivateState || eReason == eInactivateState) // update state
324  {
325  EnterCriticalSection(&m_hDataSafe);
326  m_eState= eReason == eActivateState?eActive:eInactivateState;
327  LeaveCriticalSection(&m_hDataSafe);
328  }
329 
330  if (m_eState == eInactivateState && eReason == ePreWrite) // shut it down
331  {
332  EnterCriticalSection(&m_hDataSafe);
333  m_eState= eInactive;
334  for (int i= 0; i<m_allIds.size(); ++i) // respond to all waiting users
335  {
336  SData sData;
337  sData.dwSize= sizeof(SBaseIn);
338  sData.pDevice= this;
339  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseIn));
340  if (sData.pHead)
341  {
342  ((SBaseIn*)sData.pHead)->eType= eResponse;
343  ((SBaseIn*)sData.pHead)->nChan= m_sInitFT.nChan;
344  ((SBaseIn*)sData.pHead)->nError= DEVICE_CLOSING;
345  ((SBaseIn*)sData.pHead)->dwSize= sizeof(SBaseIn);
346  m_pcComm->SendData(&sData, m_allIds[i]);
347  }
348  }
349  m_allIds.clear();
350  LeaveCriticalSection(&m_hDataSafe);
351  ResetEvent(m_hNext);
352  m_nProcessed= 0;
353  m_bRead= false;
354  // do this for the full beffer length
355  for (DWORD i= 0; i<m_sInitFT.dwBuff;++i) // now set these pins to default
356  aucBuff[i]= (aucBuff[i]&m_ucMask)|m_ucDefault;
357  } else if (m_eState == eActive && eReason == ePreWrite) // write the next set of data
358  {
359  EnterCriticalSection(&m_hDataSafe);
360  m_nProcessed= (int)m_allIds.size(); // current number of triggers proccesed
361  LeaveCriticalSection(&m_hDataSafe);
362  if (m_nProcessed)
363  {
364  //int k= 0;
365  DWORD i= 0;
366  for (DWORD j= 0; j<m_sInit.dwClkPerData; ++j)
367  aucBuff[i++]= (aucBuff[i]&m_ucMask)|1<<m_sInit.ucClk;
368  for (DWORD j= 0; j<m_sInit.dwClkPerData; ++j)
369  aucBuff[i++]= (aucBuff[i]&m_ucMask)|(1<<m_sInit.ucLatch|1<<m_sInit.ucClk);
370  for (;i<(4+m_sInit.dwBoards*8*2)*m_sInit.dwClkPerData;)
371  {
372  for (DWORD j= 0; j<m_sInit.dwClkPerData; ++j)
373  aucBuff[i++]= (aucBuff[i]&m_ucMask)|1<<m_sInit.ucLatch;
374  for (DWORD j= 0; j<m_sInit.dwClkPerData; ++j)
375  aucBuff[i++]= (aucBuff[i]&m_ucMask)|(1<<m_sInit.ucLatch|1<<m_sInit.ucClk);
376  //++k;
377  }
378  m_bRead= true;
379  m_dInitial= g_cTimer.Seconds(); // time right before reading
380  }
381  } else if (m_eState == eActive && eReason == ePostWrite) // let user know if error and set buffer to default.
382  {
383  if (m_bRead)
384  {
385  if (nError)
386  {
387  for (int i= 0; i<m_nProcessed; ++i) // if error, notfiy here
388  {
389  SData sData;
390  sData.dwSize= sizeof(SBaseOut);
391  sData.pDevice= this;
392  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseOut));
393  if (sData.pHead)
394  {
395  ((SBaseOut*)sData.pHead)->sBaseIn.eType= eResponseExD;
396  ((SBaseOut*)sData.pHead)->sBaseIn.nChan= m_sInitFT.nChan;
397  ((SBaseOut*)sData.pHead)->sBaseIn.nError= nError;
398  ((SBaseOut*)sData.pHead)->sBaseIn.dwSize= sizeof(SBaseOut);
399  ((SBaseOut*)sData.pHead)->dDouble= m_dInitial;
400  EnterCriticalSection(&m_hDataSafe);
401  m_pcComm->SendData(&sData, m_allIds[i]);
402  LeaveCriticalSection(&m_hDataSafe);
403  }
404  }
405  m_bRead= false;
406  EnterCriticalSection(&m_hDataSafe);
407  if (!m_sInit.bContinuous)
408  m_allIds.erase(m_allIds.begin(), m_allIds.begin() + m_nProcessed);
409  if (!m_allIds.size())
410  ResetEvent(m_hNext);
411  LeaveCriticalSection(&m_hDataSafe);
412  m_nProcessed= 0;
413  }
414  for (DWORD i= 0; i<(m_sInit.dwBoards*8*2+2+4)*m_sInit.dwClkPerData;++i)
415  aucBuff[i]= (aucBuff[i]&m_ucMask)|m_ucDefault;
416  }
417  } else if (m_eState == eActive && eReason == ePostRead) // respond to user
418  {
419  if (m_bRead)
420  {
421  aucBuff = (unsigned char *)m_pcMemRing->GetIndexMemoryUnsafe(*(int *)pHead);
422  for (int j= 0; j<m_nProcessed; ++j) // notify users
423  {
424  SData sData;
425  sData.dwSize= sizeof(SBaseOut)+sizeof(SBase)+sizeof(bool)*m_sInit.dwBoards*8;
426  sData.pDevice= this;
427  sData.pHead= m_pcMemPool->PoolAcquire(sData.dwSize);
428  if (sData.pHead)
429  {
430  ((SBaseOut*)sData.pHead)->sBaseIn.eType= eResponseExD;
431  ((SBaseOut*)sData.pHead)->sBaseIn.nChan= m_sInitFT.nChan;
432  ((SBaseOut*)sData.pHead)->sBaseIn.nError= nError;
433  ((SBaseOut*)sData.pHead)->sBaseIn.dwSize= sData.dwSize;
434  ((SBaseOut*)sData.pHead)->dDouble= m_dInitial;
435  ((SBase*)((char*)sData.pHead+sizeof(SBaseOut)))->eType= eFTDIMultiReadData;
436  ((SBase*)((char*)sData.pHead+sizeof(SBaseOut)))->dwSize= sizeof(SBase)+sizeof(bool)*m_sInit.dwBoards*8;
437  bool* bVal= (bool*)((char*)sData.pHead+sizeof(SBaseOut)+sizeof(SBase));
438  for (DWORD i= 0; i<m_sInit.dwBoards*8; ++i)
439  bVal[i]= (aucBuff[(3+i*2)*m_sInit.dwClkPerData]&1<<m_sInit.ucData) != 0;
440  EnterCriticalSection(&m_hDataSafe);
441  if (m_pcComm->SendData(&sData, m_allIds[j]))
442  m_allIds[j] = -1;
443  LeaveCriticalSection(&m_hDataSafe);
444  }
445  }
446  m_bRead= false;
447  EnterCriticalSection(&m_hDataSafe);
448  if (!m_sInit.bContinuous)
449  m_allIds.erase(m_allIds.begin(), m_allIds.begin() + m_nProcessed);
450  int k = 0;
451  while (k < m_allIds.size())
452  {
453  if (m_allIds[k] == -1)
454  m_allIds.erase(m_allIds.begin() + k);
455  else
456  k += 1;
457  }
458  if (!m_allIds.size())
459  ResetEvent(m_hNext);
460  LeaveCriticalSection(&m_hDataSafe);
461  m_nProcessed= 0;
462  }
463  }
464  return true;
465 }
466 
467 EStateFTDI CMultiRPeriph::GetState()
468 {
469  EnterCriticalSection(&m_hDataSafe);
470  EStateFTDI eState= m_eState;
471  LeaveCriticalSection(&m_hDataSafe);
472  return eState;
473 }
474 
475 void CMultiRPeriph::ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
476 {
477  if(m_bError)
478  return;
479  // only trigger
480  if (!pHead || dwSize != sizeof(SBaseIn) || (((SBaseIn*)pHead)->eType != eTrigger &&
481  ((SBaseIn*)pHead)->eType != eCancelReadRequest) || ((SBaseIn*)pHead)->dwSize != dwSize)
482  {
483  SData sData;
484  sData.dwSize= sizeof(SBaseIn);
485  sData.pDevice= this;
486  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseIn));
487  if (sData.pHead)
488  {
489  ((SBaseIn*)sData.pHead)->dwSize= sizeof(SBaseIn);
490  ((SBaseIn*)sData.pHead)->eType= eResponse;
491  ((SBaseIn*)sData.pHead)->nChan= m_sInitFT.nChan;
492  ((SBaseIn*)sData.pHead)->nError= INVALID_COMMAND;
493  m_pcComm->SendData(&sData, llId);
494  }
495  return;
496  }
497 
498  int nError= 0;
499  EQueryType eResp = eResponse;
500  if (((SBaseIn*)pHead)->eType == eTrigger) // request read
501  {
502  int k;
503  EnterCriticalSection(&m_hDataSafe);
504  if (m_eState == eActive)
505  {
506  for (k = 0; k < m_allIds.size(); ++k)
507  if (m_allIds[k] == llId)
508  break;
509  if (!m_sInit.bContinuous || k == m_allIds.size())
510  {
511  m_allIds.push_back(llId);
512  SetEvent(m_hNext);
513  } else
514  nError = ALREADY_OPEN;
515  } else
516  nError= INACTIVE_DEVICE;
517  LeaveCriticalSection(&m_hDataSafe);
518  } else // remove read request
519  {
520  EnterCriticalSection(&m_hDataSafe);
521  for (int k = 0; k < m_allIds.size(); ++k)
522  {
523  if (m_allIds[k] == llId)
524  {
525  m_allIds[k] = -1;
526  break;
527  }
528  }
529  LeaveCriticalSection(&m_hDataSafe);
530  eResp = eCancelReadRequest;
531  }
532 
533  if (nError || eResp != eResponse)
534  {
535  SData sData;
536  sData.dwSize= sizeof(SBaseIn);
537  sData.pDevice= this;
538  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseIn));
539  if (sData.pHead)
540  {
541  ((SBaseIn*)sData.pHead)->dwSize= sizeof(SBaseIn);
542  ((SBaseIn*)sData.pHead)->eType= eResp;
543  ((SBaseIn*)sData.pHead)->nChan= m_sInitFT.nChan;
544  ((SBaseIn*)sData.pHead)->nError= nError;
545  m_pcComm->SendData(&sData, llId);
546  }
547  }
548 }
549 
550 
551 
552 CPinWPeriph::CPinWPeriph(const SPinInit &sPinInit, CComm *pcComm, const SInitPeriphFT &sInitFT,
553  int &nError, HANDLE hNewData, CTimer* pcTimer) : CPeriphFTDI(PIN_W_P, sInitFT), m_sInit(sPinInit),
554  m_aucData(sPinInit.usBytesUsed, sPinInit.ucInitialVal&sPinInit.ucActivePins), m_ucMask(~sPinInit.ucActivePins),
555  m_ucLast(sPinInit.ucInitialVal&sPinInit.ucActivePins), m_allIds(hNewData)
556 {
557  nError= 0;
558  m_bError= true;
559  m_pcMemRing = NULL;
560  InitializeCriticalSection(&m_hDataSafe);
561  m_pcMemPool= new CMemPool;
562  // minw has to be at least as large as required for writing full boards, dwbuff also has to be as large
563  if (!pcComm || sInitFT.dwMinSizeW < sPinInit.usBytesUsed || m_sInitFT.dwBuff < sInitFT.dwMinSizeW
564  || !sPinInit.usBytesUsed || !sPinInit.ucActivePins || !pcTimer || !hNewData)
565  {
566  nError= BAD_INPUT_PARAMS;
567  return;
568  }
569  m_pcComm= pcComm;
570  m_pcTimer= pcTimer;
571  m_bUpdated= false;
572  m_bChanged= false;
573  m_nProcessed= 0;
574  m_bError= false;
575  m_eState= eInactivateState;
576  m_hNext= hNewData; // you set this when new data is availible to make channel go
577 }
578 
579 DWORD CPinWPeriph::GetInfo(void* pHead, DWORD dwSize)
580 {
581  if (!pHead)
582  return sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SPinInit)+sizeof(SInitPeriphFT);
583  if (dwSize<sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SPinInit)+sizeof(SInitPeriphFT))
584  return 0;
585 
586  ((SBaseOut*)pHead)->sBaseIn.dwSize= sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SPinInit)+sizeof(SInitPeriphFT);
587  ((SBaseOut*)pHead)->sBaseIn.eType= eResponseEx;
588  ((SBaseOut*)pHead)->sBaseIn.nChan= m_sInitFT.nChan;
589  ((SBaseOut*)pHead)->sBaseIn.nError= 0;
590  ((SBaseOut*)pHead)->bActive= GetState() == eActive;
591  _tcsncpy_s(((SBaseOut*)pHead)->szName, DEVICE_NAME_SIZE, m_csName.c_str(), _TRUNCATE);
592  pHead= (char*)pHead+ sizeof(SBaseOut);
593 
594  ((SBase*)pHead)->dwSize= sizeof(SInitPeriphFT)+sizeof(SBase);
595  ((SBase*)pHead)->eType= eFTDIPeriphInit;
596  pHead= (char*)pHead+ sizeof(SBase);
597  memcpy(pHead, &m_sInitFT, sizeof(SInitPeriphFT));
598  pHead= (char*)pHead+ sizeof(SInitPeriphFT);
599 
600  ((SBase*)pHead)->dwSize= sizeof(SPinInit)+sizeof(SBase);
601  ((SBase*)pHead)->eType= eFTDIPinWriteInit;
602  pHead= (char*)pHead+ sizeof(SBase);
603  memcpy(pHead, &m_sInit, sizeof(SPinInit));
604 
605  return sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SPinInit)+sizeof(SInitPeriphFT);
606 }
607 
608 CPinWPeriph::~CPinWPeriph()
609 {
610  DeleteCriticalSection(&m_hDataSafe);
611  delete m_pcMemPool;
612 }
613 
614 bool CPinWPeriph::DoWork(void *pHead, DWORD dwSize, FT_HANDLE ftHandle, EStateFTDI eReason, int nError)
615 {
616  if (m_bError)
617  return true;
618  unsigned char *aucBuff= (unsigned char *)pHead;
619  bool bNotEmpty;
620 
621  if (eReason == eActivateState || eReason == eInactivateState) // update state
622  {
623  EnterCriticalSection(&m_hDataSafe);
624  m_eState= eReason == eActivateState?eActive:eInactivateState;
625  LeaveCriticalSection(&m_hDataSafe);
626  } else if (eReason == eRecover)
627  {
628  EnterCriticalSection(&m_hDataSafe);
629  if (m_eState == eActive || m_eState == eInactivateState)
630  {
631  m_bUpdated= true; // clock out last data again
632  SetEvent(m_hNext);
633  }
634  LeaveCriticalSection(&m_hDataSafe);
635  }
636 
637  if (m_eState == eInactivateState && eReason == ePreWrite) // shut it down
638  {
639  EnterCriticalSection(&m_hDataSafe);
640  m_eState= eInactive;
641  m_bUpdated= false;
642  LeaveCriticalSection(&m_hDataSafe);
643  ResetEvent(m_hNext);
644  // no new requests can be added because state is inactive
645  while (m_allIds.GetSize()) // respond to all waiting users
646  {
647  SData sData;
648  sData.dwSize= sizeof(SBaseIn);
649  sData.pDevice= this;
650  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseIn));
651  if (sData.pHead)
652  {
653  ((SBaseIn*)sData.pHead)->eType= eResponse;
654  ((SBaseIn*)sData.pHead)->nChan= m_sInitFT.nChan;
655  ((SBaseIn*)sData.pHead)->nError= DEVICE_CLOSING;
656  ((SBaseIn*)sData.pHead)->dwSize= sizeof(SBaseIn);
657  m_pcComm->SendData(&sData, m_allIds.Front(true, bNotEmpty));
658  }
659  }
660  m_nProcessed= 0;
661  m_bChanged= false;
662  // update full buffer
663  for (DWORD i= 0; i<m_sInitFT.dwBuff;++i) // now set these pins to last value
664  aucBuff[i]= (aucBuff[i]&m_ucMask)|m_ucLast;
665  } else if (m_eState == eActive && eReason == ePreWrite) // write the next set of data
666  {
667  EnterCriticalSection(&m_hDataSafe);
668  if (m_bUpdated)
669  {
670  unsigned short i= 0; // write data from buffer
671  m_ucLast= m_aucData[m_sInit.usBytesUsed-1];
672  for (; i<m_sInit.usBytesUsed; ++i)
673  {
674  aucBuff[i]= (aucBuff[i]&m_ucMask)|m_aucData[i];
675  m_aucData[i]= m_ucLast;
676  }
677  for (; i<m_sInitFT.dwBuff; ++i) // write last data until end of buffer
678  aucBuff[i]= (aucBuff[i]&m_ucMask)|m_ucLast;
679  m_bUpdated= false; // done updating
680  m_bChanged= true;
681  m_nProcessed= m_allIds.GetSize(); // current number of updates proccesed
682  m_dInitial= g_cTimer.Seconds(); // time right before writing
683  ResetEvent(m_hNext);
684  }
685  LeaveCriticalSection(&m_hDataSafe);
686  } else if (m_eState == eActive && eReason == ePostWrite)
687  {
688  if (m_bChanged)
689  for (unsigned short i= 0; i<m_sInit.usBytesUsed;++i)
690  aucBuff[i]= (aucBuff[i]&m_ucMask)|m_ucLast;
691  } else if (m_eState == eActive && eReason == ePostRead) // now let user know if succesful and set buffer to default.
692  {
693  if (m_bChanged)
694  {
695  for (int i= 0; i<m_nProcessed; ++i)
696  {
697  SData sData;
698  sData.dwSize= sizeof(SBaseOut);
699  sData.pDevice= this;
700  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseOut));
701  if (sData.pHead)
702  {
703  ((SBaseOut*)sData.pHead)->sBaseIn.eType= eResponseExD;
704  ((SBaseOut*)sData.pHead)->sBaseIn.nChan= m_sInitFT.nChan;
705  ((SBaseOut*)sData.pHead)->sBaseIn.nError= nError;
706  ((SBaseOut*)sData.pHead)->sBaseIn.dwSize= sizeof(SBaseOut);
707  ((SBaseOut*)sData.pHead)->dDouble= m_dInitial;
708  m_pcComm->SendData(&sData, m_allIds.Front(true, bNotEmpty));
709  }
710  }
711  m_nProcessed= 0;
712  m_bChanged= false;
713  }
714  }
715  return true;
716 }
717 
718 EStateFTDI CPinWPeriph::GetState()
719 {
720  EnterCriticalSection(&m_hDataSafe);
721  EStateFTDI eState= m_eState;
722  LeaveCriticalSection(&m_hDataSafe);
723  return eState;
724 }
725 
726 void CPinWPeriph::ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
727 {
728  if(m_bError)
729  return;
730  if (!pHead || dwSize < sizeof(SBaseIn) + sizeof(SBase) || ((SBaseIn*)pHead)->dwSize != dwSize || ((SBaseIn*)pHead)->eType != eData ||
731  (!(((SBase*)((char*)pHead+sizeof(SBaseIn)))->eType == eFTDIPinWDataArray && dwSize > sizeof(SBaseIn) + sizeof(SBase) &&
732  !((dwSize-sizeof(SBase)-sizeof(SBaseIn))%sizeof(SPinWData))) && !(((SBase*)((char*)pHead+sizeof(SBaseIn)))->eType == eFTDIPinWDataBufArray &&
733  dwSize > sizeof(SBaseIn)+sizeof(SBase)+sizeof(SPinWData)))) // there has to be at least some data
734  {
735  SData sData;
736  sData.dwSize= sizeof(SBaseIn);
737  sData.pDevice= this;
738  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseIn));
739  if (sData.pHead)
740  {
741  ((SBaseIn*)sData.pHead)->dwSize= sizeof(SBaseIn);
742  ((SBaseIn*)sData.pHead)->eType= eResponse;
743  ((SBaseIn*)sData.pHead)->nChan= m_sInitFT.nChan;
744  ((SBaseIn*)sData.pHead)->nError= INVALID_COMMAND;
745  m_pcComm->SendData(&sData, llId);
746  }
747  return;
748  }
749 
750  int nLen= 0;
751  unsigned char* aucData= NULL;
752  SPinWData* asPinData= NULL;
753  SPinWData sPinData;
754  unsigned char ucPinSelect;
755  int nError= 0;
756  if (((SBaseIn*)((char*)pHead+sizeof(SBaseIn)))->eType == eFTDIPinWDataArray)
757  {
758  nLen= (dwSize-sizeof(SBaseIn)-sizeof(SBase))/sizeof(SPinWData);
759  asPinData= (SPinWData*)((char*)pHead+sizeof(SBase)+sizeof(SBaseIn));
760  int nSum= 0;
761  for (int i= 0; i<nLen; ++i)
762  nSum += asPinData[i].usRepeat;
763  if (nSum>m_sInit.usBytesUsed)
764  nError= BAD_INPUT_PARAMS;
765  } else
766  {
767  nLen= dwSize-sizeof(SBaseIn)-sizeof(SBase)-sizeof(SPinWData);
768  aucData= (unsigned char*)((char*)pHead+sizeof(SBase)+sizeof(SBaseIn)+sizeof(SPinWData));
769  sPinData= *(SPinWData*)((char*)pHead+sizeof(SBase)+sizeof(SBaseIn));
770  sPinData.ucPinSelect= sPinData.ucPinSelect&(~m_ucMask);
771  ucPinSelect= ~sPinData.ucPinSelect;
772  if (nLen>m_sInit.usBytesUsed)
773  nError= BAD_INPUT_PARAMS;
774  }
775  if (!nError)
776  {
777  EnterCriticalSection(&m_hDataSafe);
778  if (m_eState == eActive)
779  {
780  if (((SBaseIn*)((char*)pHead+sizeof(SBaseIn)))->eType == eFTDIPinWDataArray)
781  {
782  int i= 0;
783  int k= 0;
784  unsigned char ucVal;
785  for (;i<nLen; ++i)
786  {
787  asPinData[i].ucPinSelect= asPinData[i].ucPinSelect&(~m_ucMask); // make sure we only touch valid pins
788  ucPinSelect= ~asPinData[i].ucPinSelect; // pins we don't want to update stay the same
789  ucVal= asPinData[i].ucValue&asPinData[i].ucPinSelect; // select pins we want to update
790  int kTemp= k;
791  for (; k < kTemp+asPinData[i].usRepeat; ++k)
792  m_aucData[k]= (m_aucData[k]&ucPinSelect)|ucVal;
793  }
794  for (;k<m_sInit.usBytesUsed; ++k)
795  m_aucData[k]= (m_aucData[k]&ucPinSelect)|ucVal;
796  } else
797  {
798  int i= 0;
799  for (;i<nLen; ++i)
800  m_aucData[i]= (m_aucData[i]&ucPinSelect)|(aucData[i]&sPinData.ucPinSelect);
801  const unsigned char ucVal= aucData[i-1]&sPinData.ucPinSelect; // padd the same data until end of array
802  for (;i<m_sInit.usBytesUsed; ++i)
803  m_aucData[i]= (m_aucData[i]&ucPinSelect)|ucVal;
804  }
805  m_bUpdated= true;
806  m_allIds.Push(llId); // pipe to notify of success
807  SetEvent(m_hNext); // update only in cc
808  } else
809  nError= INACTIVE_DEVICE;
810  LeaveCriticalSection(&m_hDataSafe);
811  }
812 
813  if (nError)
814  {
815  SData sData;
816  sData.dwSize= sizeof(SBaseIn);
817  sData.pDevice= this;
818  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseIn));
819  if (sData.pHead)
820  {
821  ((SBaseIn*)sData.pHead)->dwSize= sizeof(SBaseIn);
822  ((SBaseIn*)sData.pHead)->eType= eResponse;
823  ((SBaseIn*)sData.pHead)->nChan= m_sInitFT.nChan;
824  ((SBaseIn*)sData.pHead)->nError= nError;
825  m_pcComm->SendData(&sData, llId);
826  }
827  }
828 }
829 
830 
831 
832 CPinRPeriph::CPinRPeriph(const SPinInit &sPinInit, CComm *pcComm, const SInitPeriphFT &sInitFT,
833  int &nError, HANDLE hNewData, CTimer* pcTimer) : CPeriphFTDI(PIN_R_P, sInitFT), m_sInit(sPinInit),
834  m_ucMask(~sPinInit.ucActivePins)
835 {
836  nError= 0;
837  m_bError= true;
838  m_pcMemRing = NULL;
839  InitializeCriticalSection(&m_hDataSafe);
840  m_pcMemPool= new CMemPool;
841  // minw has to be at least as large as required for writing full boards, dwbuff also has to be as large
842  if (!pcComm || sInitFT.dwMinSizeW < sPinInit.usBytesUsed ||
843  sInitFT.dwBuff < sInitFT.dwMinSizeW || sInitFT.dwMinSizeW != sInitFT.dwMinSizeR ||
844  !sPinInit.usBytesUsed || !sPinInit.ucActivePins || !pcTimer || !hNewData)
845  {
846  nError= BAD_INPUT_PARAMS;
847  return;
848  }
849  m_pcComm= pcComm;
850  m_pcTimer= pcTimer;
851  m_bRead= false;
852  m_nProcessed= 0;
853  m_bError= false;
854  m_eState= eInactivateState;
855  m_hNext= hNewData; // you set this when new data is availible
856 }
857 
858 DWORD CPinRPeriph::GetInfo(void* pHead, DWORD dwSize)
859 {
860  if (!pHead)
861  return sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SPinInit)+sizeof(SInitPeriphFT);
862  if (dwSize<sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SPinInit)+sizeof(SInitPeriphFT))
863  return 0;
864 
865  ((SBaseOut*)pHead)->sBaseIn.dwSize= sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SPinInit)+sizeof(SInitPeriphFT);
866  ((SBaseOut*)pHead)->sBaseIn.eType= eResponseEx;
867  ((SBaseOut*)pHead)->sBaseIn.nChan= m_sInitFT.nChan;
868  ((SBaseOut*)pHead)->sBaseIn.nError= 0;
869  ((SBaseOut*)pHead)->bActive= GetState() == eActive;
870  _tcsncpy_s(((SBaseOut*)pHead)->szName, DEVICE_NAME_SIZE, m_csName.c_str(), _TRUNCATE);
871  pHead= (char*)pHead+ sizeof(SBaseOut);
872 
873  ((SBase*)pHead)->dwSize= sizeof(SInitPeriphFT)+sizeof(SBase);
874  ((SBase*)pHead)->eType= eFTDIPeriphInit;
875  pHead= (char*)pHead+ sizeof(SBase);
876  memcpy(pHead, &m_sInitFT, sizeof(SInitPeriphFT));
877  pHead= (char*)pHead+ sizeof(SInitPeriphFT);
878 
879  ((SBase*)pHead)->dwSize= sizeof(SPinInit)+sizeof(SBase);
880  ((SBase*)pHead)->eType= eFTDIPinReadInit;
881  pHead= (char*)pHead+ sizeof(SBase);
882  memcpy(pHead, &m_sInit, sizeof(SPinInit));
883 
884  return sizeof(SBaseOut)+2*sizeof(SBase)+sizeof(SPinInit)+sizeof(SInitPeriphFT);
885 }
886 
887 CPinRPeriph::~CPinRPeriph()
888 {
889  DeleteCriticalSection(&m_hDataSafe);
890  delete m_pcMemPool;
891 }
892 
893 bool CPinRPeriph::DoWork(void *pHead, DWORD dwSize, FT_HANDLE ftHandle, EStateFTDI eReason, int nError)
894 {
895  if (m_bError)
896  return true;
897  unsigned char *aucBuff= (unsigned char *)pHead;
898 
899  if (eReason == eActivateState || eReason == eInactivateState) // update state
900  {
901  EnterCriticalSection(&m_hDataSafe);
902  m_eState= eReason == eActivateState?eActive:eInactivateState;
903  LeaveCriticalSection(&m_hDataSafe);
904  }
905 
906  if (m_eState == eInactivateState && eReason == ePreWrite) // shut it down
907  {
908  EnterCriticalSection(&m_hDataSafe);
909  m_eState= eInactive;
910  for (int i= 0; i<m_allIds.size(); ++i) // respond to all waiting users
911  {
912  SData sData;
913  sData.dwSize= sizeof(SBaseIn);
914  sData.pDevice= this;
915  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseIn));
916  if (sData.pHead)
917  {
918  ((SBaseIn*)sData.pHead)->eType= eResponse;
919  ((SBaseIn*)sData.pHead)->nChan= m_sInitFT.nChan;
920  ((SBaseIn*)sData.pHead)->nError= DEVICE_CLOSING;
921  ((SBaseIn*)sData.pHead)->dwSize= sizeof(SBaseIn);
922  m_pcComm->SendData(&sData, m_allIds[i]);
923  }
924  }
925  m_allIds.clear();
926  LeaveCriticalSection(&m_hDataSafe);
927  ResetEvent(m_hNext);
928  m_nProcessed= 0;
929  m_bRead= false;
930  //for (DWORD i= 0; i<m_sInitFT.dwBuff;++i) // now set these pins to default
931  // aucBuff[i]= aucBuff[i]&m_ucMask;
932  } else if (m_eState == eActive && eReason == ePreWrite)
933  {
934  EnterCriticalSection(&m_hDataSafe);
935  m_nProcessed= (int)m_allIds.size(); // current number of triggers proccesed (only one if cont)
936  LeaveCriticalSection(&m_hDataSafe);
937  if (m_nProcessed)
938  {
939  m_bRead= true;
940  m_dInitial= g_cTimer.Seconds(); // time right before reading
941  }
942  } else if (m_eState == eActive && eReason == ePostWrite) // let user know if error
943  {
944  if (m_bRead)
945  {
946  if (nError)
947  {
948  for (int i= 0; i<m_nProcessed; ++i) // if error, notfiy here
949  {
950  SData sData;
951  sData.dwSize= sizeof(SBaseOut);
952  sData.pDevice= this;
953  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseOut));
954  if (sData.pHead)
955  {
956  ((SBaseOut*)sData.pHead)->sBaseIn.eType= eResponseExD;
957  ((SBaseOut*)sData.pHead)->sBaseIn.nChan= m_sInitFT.nChan;
958  ((SBaseOut*)sData.pHead)->sBaseIn.nError= nError;
959  ((SBaseOut*)sData.pHead)->sBaseIn.dwSize= sizeof(SBaseOut);
960  ((SBaseOut*)sData.pHead)->dDouble= m_dInitial;
961  EnterCriticalSection(&m_hDataSafe);
962  m_pcComm->SendData(&sData, m_allIds[i]);
963  LeaveCriticalSection(&m_hDataSafe);
964  }
965  }
966  m_bRead= false;
967  EnterCriticalSection(&m_hDataSafe);
968  if (!m_sInit.bContinuous)
969  m_allIds.erase(m_allIds.begin(), m_allIds.begin() + m_nProcessed);
970  if (!m_allIds.size())
971  ResetEvent(m_hNext);
972  LeaveCriticalSection(&m_hDataSafe);
973  m_nProcessed= 0;
974  }
975  }
976  } else if (m_eState == eActive && eReason == ePostRead) // respond to user
977  {
978  if (m_bRead)
979  {
980  aucBuff = (unsigned char *)m_pcMemRing->GetIndexMemoryUnsafe(*(int *)pHead);
981  for (int j= 0; j<m_nProcessed; ++j) // notify users
982  {
983  SData sData;
984  sData.dwSize= sizeof(SBaseOut)+sizeof(SBase)+sizeof(unsigned char)*m_sInit.usBytesUsed;
985  sData.pDevice= this;
986  sData.pHead= m_pcMemPool->PoolAcquire(sData.dwSize);
987  if (sData.pHead)
988  {
989  ((SBaseOut*)sData.pHead)->sBaseIn.eType= eResponseExD;
990  ((SBaseOut*)sData.pHead)->sBaseIn.nChan= m_sInitFT.nChan;
991  ((SBaseOut*)sData.pHead)->sBaseIn.nError= nError;
992  ((SBaseOut*)sData.pHead)->sBaseIn.dwSize= sData.dwSize;
993  ((SBaseOut*)sData.pHead)->dDouble= m_dInitial;
994  ((SBase*)((unsigned char*)sData.pHead+sizeof(SBaseOut)))->eType= eFTDIPinRDataArray;
995  ((SBase*)((unsigned char*)sData.pHead+sizeof(SBaseOut)))->dwSize= sizeof(SBase)+sizeof(unsigned char)*m_sInit.usBytesUsed;
996  unsigned char* ucVal= (unsigned char*)sData.pHead+sizeof(SBaseOut)+sizeof(SBase);
997  for (unsigned short i= 0; i<m_sInit.usBytesUsed; ++i)
998  ucVal[i]= aucBuff[i]&~m_ucMask;
999  EnterCriticalSection(&m_hDataSafe);
1000  if (m_pcComm->SendData(&sData, m_allIds[j]))
1001  m_allIds[j] = -1;
1002  LeaveCriticalSection(&m_hDataSafe);
1003  }
1004  }
1005  m_bRead= false;
1006  EnterCriticalSection(&m_hDataSafe);
1007  if (!m_sInit.bContinuous)
1008  m_allIds.erase(m_allIds.begin(), m_allIds.begin() + m_nProcessed);
1009  int k = 0;
1010  while (k < m_allIds.size())
1011  {
1012  if (m_allIds[k] == -1)
1013  m_allIds.erase(m_allIds.begin() + k);
1014  else
1015  k += 1;
1016  }
1017  if (!m_allIds.size())
1018  ResetEvent(m_hNext);
1019  LeaveCriticalSection(&m_hDataSafe);
1020  m_nProcessed= 0;
1021  }
1022  }
1023  return true;
1024 }
1025 
1026 EStateFTDI CPinRPeriph::GetState()
1027 {
1028  EnterCriticalSection(&m_hDataSafe);
1029  EStateFTDI eState= m_eState;
1030  LeaveCriticalSection(&m_hDataSafe);
1031  return eState;
1032 }
1033 
1034 void CPinRPeriph::ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
1035 {
1036  if(m_bError)
1037  return;
1038  // only trigger
1039  if (!pHead || dwSize != sizeof(SBaseIn) || (((SBaseIn*)pHead)->eType != eTrigger &&
1040  ((SBaseIn*)pHead)->eType != eCancelReadRequest) || ((SBaseIn*)pHead)->dwSize != dwSize)
1041  {
1042  SData sData;
1043  sData.dwSize= sizeof(SBaseIn);
1044  sData.pDevice= this;
1045  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseIn));
1046  if (sData.pHead)
1047  {
1048  ((SBaseIn*)sData.pHead)->dwSize= sizeof(SBaseIn);
1049  ((SBaseIn*)sData.pHead)->eType= eResponse;
1050  ((SBaseIn*)sData.pHead)->nChan= m_sInitFT.nChan;
1051  ((SBaseIn*)sData.pHead)->nError= INVALID_COMMAND;
1052  m_pcComm->SendData(&sData, llId);
1053  }
1054  return;
1055  }
1056 
1057  int nError= 0;
1058  EQueryType eResp = eResponse;
1059  if (((SBaseIn*)pHead)->eType == eTrigger) // request read
1060  {
1061  int k;
1062  EnterCriticalSection(&m_hDataSafe);
1063  if (m_eState == eActive)
1064  {
1065  for (k = 0; k < m_allIds.size(); ++k)
1066  if (m_allIds[k] == llId)
1067  break;
1068  if (!m_sInit.bContinuous || k == m_allIds.size())
1069  {
1070  m_allIds.push_back(llId);
1071  SetEvent(m_hNext);
1072  } else
1073  nError = ALREADY_OPEN;
1074  } else
1075  nError= INACTIVE_DEVICE;
1076  LeaveCriticalSection(&m_hDataSafe);
1077  } else // remove read request
1078  {
1079  EnterCriticalSection(&m_hDataSafe);
1080  for (int k = 0; k < m_allIds.size(); ++k)
1081  {
1082  if (m_allIds[k] == llId)
1083  {
1084  m_allIds[k] = -1;
1085  break;
1086  }
1087  }
1088  LeaveCriticalSection(&m_hDataSafe);
1089  eResp = eCancelReadRequest;
1090  }
1091 
1092  if (nError || eResp != eResponse)
1093  {
1094  SData sData;
1095  sData.dwSize= sizeof(SBaseIn);
1096  sData.pDevice= this;
1097  sData.pHead= m_pcMemPool->PoolAcquire(sizeof(SBaseIn));
1098  if (sData.pHead)
1099  {
1100  ((SBaseIn*)sData.pHead)->dwSize= sizeof(SBaseIn);
1101  ((SBaseIn*)sData.pHead)->eType= eResp;
1102  ((SBaseIn*)sData.pHead)->nChan= m_sInitFT.nChan;
1103  ((SBaseIn*)sData.pHead)->nError= nError;
1104  m_pcComm->SendData(&sData, llId);
1105  }
1106  }
1107 }
DWORD GetInfo(void *pHead, DWORD dwSize)
Definition: cpl ft io.cpp:858
bool DoWork(void *pHead, DWORD dwSize, FT_HANDLE ftHandle, EStateFTDI eReason, int nError)
Definition: cpl ft io.cpp:317
bool DoWork(void *pHead, DWORD dwSize, FT_HANDLE ftHandle, EStateFTDI eReason, int nError)
Definition: cpl ft io.cpp:614
virtual int SendData(const SData *pData, __int64 llId)=0
bool DoWork(void *pHead, DWORD dwSize, FT_HANDLE ftHandle, EStateFTDI eReason, int nError)
Definition: cpl ft io.cpp:893
unsigned char ucInitialVal
Definition: cpl defs.h:281
void ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
Definition: cpl ft io.cpp:475
DWORD GetInfo(void *pHead, DWORD dwSize)
Definition: cpl ft io.cpp:579
void ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
Definition: cpl ft io.cpp:191
unsigned char ucActivePins
Definition: cpl defs.h:278
DWORD GetInfo(void *pHead, DWORD dwSize)
Definition: cpl ft io.cpp:40
bool DoWork(void *pHead, DWORD dwSize, FT_HANDLE ftHandle, EStateFTDI eReason, int nError)
Definition: cpl ft io.cpp:75
CMultiWPeriph(const SValveInit &sValveInit, CComm *pcComm, const SInitPeriphFT &sInitFT, int &nError, HANDLE hNewData, CTimer *pcTimer)
Definition: cpl ft io.cpp:11
int GetSize()
Definition: cpl queue.h:52
void ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
Definition: cpl ft io.cpp:726
void ProcessData(const void *pHead, DWORD dwSize, __int64 llId)
Definition: cpl ft io.cpp:1034
double Seconds() const
Definition: misc tools.cpp:63
DWORD GetInfo(void *pHead, DWORD dwSize)
Definition: cpl ft io.cpp:282
unsigned short usBytesUsed
Definition: cpl defs.h:275
const std::tstring m_csName
Definition: base classses.h:98
void Push(T pHead)
Definition: cpl queue.h:26
void * GetIndexMemoryUnsafe(int nIdx)
Definition: mem pool.cpp:39
T Front(bool bPop, bool &bValid)
Definition: cpl queue.h:38
CPeriphFTDI(const TCHAR szName[], const SInitPeriphFT &sInitFT)
Definition: ftdi device.h:115