mrfioc2  2.3.0
mrmDataBufTx.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2014 Brookhaven Science Associates, as Operator of
3 * Brookhaven National Laboratory.
4 * Copyright (c) 2015 Paul Scherrer Institute (PSI), Villigen, Switzerland
5 * mrfioc2 is distributed subject to a Software License Agreement found
6 * in file LICENSE that is included with this distribution.
7 \*************************************************************************/
8 #include <cstdio>
9 #include <stdexcept>
10 
11 #include <epicsTypes.h>
12 
13 #include <epicsThread.h>
14 #include <epicsInterrupt.h>
15 
16 #include <mrfCommonIO.h>
17 
18 #include "mrf/databuf.h"
19 
20 #include <epicsExport.h>
21 
22 #include "mrmDataBufTx.h"
23 
24 #define DataTxCtrl_done 0x100000
25 #define DataTxCtrl_run 0x080000
26 #define DataTxCtrl_trig 0x040000
27 #define DataTxCtrl_ena 0x020000
28 #define DataTxCtrl_mode 0x010000
29 #define DataTxCtrl_len_mask 0x0007fc
30 #define DataTxCtrl_len_max DataTxCtrl_len_mask
31 
32 mrmDataBufTx::mrmDataBufTx(const std::string& n,
33  volatile epicsUInt8* bufcontrol,
34  volatile epicsUInt8* buffer
35 ) :dataBufTx(n)
36  ,dataCtrl(bufcontrol)
37  ,dataBuf(buffer)
38  ,dataGuard()
39 {
40 }
41 
43 {
44 }
45 
46 bool
48 {
49  return (nat_ioread32(dataCtrl) &
51 }
52 
53 void
55 {
56  SCOPED_LOCK(dataGuard);
57 
58  epicsUInt32 reg=nat_ioread32(dataCtrl);
59  epicsUInt32 mask=DataTxCtrl_ena|DataTxCtrl_mode;
60  if(v)
61  reg |= mask;
62  else
63  reg &= ~mask;
64  nat_iowrite32(dataCtrl, reg);
65 }
66 
67 bool
69 {
70  epicsUInt32 reg=nat_ioread32(dataCtrl);
71 
72  if (!(reg&(DataTxCtrl_ena|DataTxCtrl_mode)))
73  throw std::runtime_error("Buffer Tx not enabled");
74  if (reg&DataTxCtrl_done)
75  return true;
76  else if (reg&DataTxCtrl_run)
77  return false;
78  else
79  throw std::runtime_error("Buffer Tx not running or done");
80 }
81 
82 
83 epicsUInt32
85 {
86  return DataTxCtrl_len_max;
87 }
88 
89 void
90 mrmDataBufTx::dataSend(epicsUInt32 len,
91  const epicsUInt8 *ubuf
92 )
93 {
94  STATIC_ASSERT(DataTxCtrl_len_max%4==0);
95 
96  if (len > DataTxCtrl_len_max)
97  throw std::out_of_range("Tx buffer is too long");
98 
99  // len must be a multiple of 4
100  len &= DataTxCtrl_len_mask;
101 
102  SCOPED_LOCK(dataGuard);
103 
104  // Zero length
105  // Seems to be required?
107 
108  // Write 4 byte words over VME
109  epicsUInt32 index;
110  for(index=0; index<len; index+=4) {
111  be_iowrite32(&dataBuf[index], *(epicsUInt32*)(&ubuf[index]) );
112  }
113 
115 
116  // Reading flushes output queue of VME bridge
117  // Actual sending is so fast that we can use busy wait here
118  // Measurements showed that we loop up to 17 times
119  while(!(nat_ioread32(dataCtrl)&DataTxCtrl_done)) {};
120 }
#define DataTxCtrl_trig
#define DataTxCtrl_len_max
#define DataTxCtrl_done
INLINE void nat_iowrite32(volatile void *addr, epicsUInt32 val)
Definition: mrfIoOpsDef.h:55
INLINE epicsUInt32 nat_ioread32(volatile void *addr)
Definition: mrfIoOpsDef.h:48
#define be_iowrite32(A, D)
Definition: mrfIoOpsDef.h:75
virtual epicsUInt32 lenMax() const OVERRIDE FINAL
#define DataTxCtrl_run
virtual void dataTxEnable(bool) OVERRIDE FINAL
#define DataTxCtrl_len_mask
#define DataTxCtrl_mode
virtual ~mrmDataBufTx()
virtual bool dataTxEnabled() const OVERRIDE FINAL
Is card configured for buffer transmission?
virtual void dataSend(epicsUInt32 len, const epicsUInt8 *buf) OVERRIDE FINAL
Transmit a byte array.
#define DataTxCtrl_ena
virtual bool dataRTS() const OVERRIDE FINAL
Is card ready to send a buffer?
mrmDataBufTx(const std::string &n, volatile epicsUInt8 *bufcontrol, volatile epicsUInt8 *buffer)