1 /**
2 * This module contains bindings to types and functions from the nodave C header <nodavesimple.h>.
3 */
4 
5 module dinodave.nodave;
6 
7 import std.stdio;
8 import core.stdc.stdio;
9 import core.stdc.stdlib;
10 
11 enum daveProtoISOTCP = 122;   /** ISO over TCP */
12 
13 /** ProfiBus/MPI speed constants to be used with newInterface */
14 enum daveSpeed9k = 0;
15 enum daveSpeed19k = 1;
16 enum daveSpeed187k = 2;
17 enum daveSpeed500k = 3;
18 enum daveSpeed1500k = 4;
19 enum daveSpeed45k = 5;
20 enum daveSpeed93k = 6;
21 
22 enum daveP = 0x80;
23 enum daveInputs = 0x81;
24 enum daveOutputs = 0x82;
25 enum daveFlags = 0x83;
26 enum daveDB = 0x84;  /** Data blocks */
27 enum daveDI = 0x85;  /** Instance data blocks */
28 enum daveLocal = 0x86;  /* not tested */
29 enum daveV = 0x87;   /* don't know what it is */
30 enum daveCounter = 28;  /** S7 counters */
31 enum daveTimer = 29; /** S7 timers */
32 enum daveCounter200 = 30;  /* IEC counters (200 family) */
33 enum daveTimer200 = 31;    /* IEC timers (200 family) */
34 
35 extern (C):
36 
37 alias daveConnection = _daveConnection;
38 alias daveInterface = _daveInterface;
39 
40 struct _daveOSserialType {
41    int rfd;
42    int wfd;
43 }
44 
45 struct PDU {
46    ubyte* header;
47    ubyte* param;
48    ubyte* data;
49    ubyte* udata;
50    int hlen;
51    int plen;
52    int dlen;
53    int udlen;
54 }
55 
56 /**
57 * A structure representing the physical connection to a PLC or a network of PLCs (e.g. like MPI).
58 * daveInterface stores all those properties that are common to a network of PLCs:
59 * - The local address used by your computer.
60 * - The speed used in this network.
61 * - The protocol type used in this network.
62 * - A name which is used when printing out debug messages.
63 *
64 * The structure daveInterface is created and initialized by daveNewInterface:
65 *
66 * --------------------
67 * daveInterface* di;
68 * di = daveNewInterface(fds, "IF1", localMPI, daveProtoXXX, daveSpeedYYY);
69 * --------------------
70 *
71 * or in D
72 * --------------------
73 * auto sock = new TcpSocket(new InternetAddress(ip, to!(ushort)(port)));
74 * fds.wfd = fds.rfd = sock.handle;
75 * daveInterface* di = daveNewInterface(fds, "IF1", 0, daveProtoISOTCP, daveSpeed9k);
76 * --------------------
77 */
78 struct _daveInterface {
79    int _timeout;
80 }
81 
82 /**
83 * A structure representing the physical connection to a single PLC.
84 * daveConnection stores all properties that are unique to a single PLC:
85 * - The MPI address of this PLC.
86 * - The rack the PLC is in.
87 * - The slot the PLC is in.
88 */
89 struct _daveConnection {
90    int AnswLen;
91    ubyte* resultPointer;
92    int maxPDUlength;
93 }
94 
95 struct daveBlockTypeEntry {
96    ubyte[2] type;
97    ushort count;
98 }
99 
100 struct daveBlockEntry {
101    ushort number;
102    ubyte[2] type;
103 }
104 
105 struct daveResult {
106    int error;
107    int length;
108    ubyte* bytes;
109 }
110 
111 struct daveResultSet {
112    int numResults;
113    daveResult* results;
114 }
115 
116 // helper
117 // ---------
118 int daveGetS8from(ubyte* b);
119 int daveGetU8from(ubyte* b);
120 int daveGetS16from(ubyte* b);
121 int daveGetU16from(ubyte* b);
122 int daveGetS32from(ubyte* b);
123 uint daveGetU32from(ubyte* b);
124 float daveGetFloatfrom(ubyte* b);
125 
126 ubyte* davePut8(ubyte* b, int v);
127 ubyte* davePut16(ubyte* b, int v);
128 ubyte* davePut32(ubyte* b, int v);
129 ubyte* davePutFloat(ubyte* b, float v);
130 void davePut8At(ubyte* b, int pos, int v);
131 void davePut16At(ubyte* b, int pos, int v);
132 void davePut32At(ubyte* b, int pos, int v);
133 void davePutFloatAt(ubyte* b, int pos, float v);
134 
135 ubyte daveToBCD(ubyte i);
136 ubyte daveFromBCD(ubyte i);
137 
138 // plc
139 // ---------
140 int daveGetS8(daveConnection* dc);
141 int daveGetU8(daveConnection* dc);
142 int daveGetS16(daveConnection* dc);
143 int daveGetU16(daveConnection* dc);
144 int daveGetS32(daveConnection* dc);
145 uint daveGetU32(daveConnection* dc);
146 float daveGetFloat(daveConnection* dc);
147 
148 int daveGetS8At(daveConnection* dc, int pos);
149 int daveGetU8At(daveConnection* dc, int pos);
150 int daveGetS16At(daveConnection* dc, int pos);
151 int daveGetU16At(daveConnection* dc, int pos);
152 int daveGetS32At(daveConnection* dc, int pos);
153 uint daveGetU32At(daveConnection* dc, int pos);
154 float daveGetFloatAt(daveConnection* dc, int pos);
155 
156 int daveSetBit(daveConnection* dc, int area, int DB, int byteAdr, int bitAdr);
157 int daveClrBit(daveConnection* dc, int area, int DB, int byteAdr, int bitAdr);
158 
159 /**
160  * Read len bytes from the PLC.
161  *
162  * Params:
163  *  dc = A daveConnection
164  *  area = Denotes whether the data comes from FLAGS, DATA BLOCKS,
165  *  DB = The number of the data block to be used. Set it to zero
166  *  start = First byte.
167  *  len = Number of bytes to read
168  *  buffer = Pointer to a memory block provided by the calling program.
169  *           If the pointer is not NULL, the result data will be copied thereto.
170  *           Hence it must be big enough to take up the result.
171  *
172  */
173 int daveReadBytes(daveConnection* dc, int area, int DB, int start, int len, void* buffer);
174 int daveWriteBytes(daveConnection* dc, int area, int DB, int start, int len, void* buffer);
175 
176 int daveReadPLCTime(daveConnection* dc);
177 // ---------
178 
179 
180 /**
181 * Get time in seconds from current read position
182 */
183 float daveGetSeconds(daveConnection* dc);
184 
185 /**
186  * Get time in seconds from random position
187  *
188  * Params:
189  *  dc = a daveConnection
190  *  pos = Position in bytes
191  *
192  * Examples:
193  * --------------------
194  * // read 4 timers: each timer has 2 bytes
195  * const(int) res = daveReadBytes(dc, daveTimer, 0, 0, 4, null);
196  * // read second of timer 2
197  * float d = daveGetSecondsAt(dc, 4);
198  * // 4 because:
199  * // | pos | timer   |
200  * // | 0   | timer 0 |
201  * // | 1   | timer 0 |
202  * // | 2   | timer 1 |
203  * // | 3   | timer 1 |
204  * // | 4   | timer 2 | <----
205  * // | 5   | timer 2 |
206  * --------------------
207  */
208 float daveGetSecondsAt(daveConnection* dc, int pos);
209 int daveGetCounterValue(daveConnection* dc);
210 int daveGetCounterValueAt(daveConnection* dc, int pos);
211 void _daveConstructUpload(PDU* p, char blockType, int blockNr);
212 void _daveConstructDoUpload(PDU* p, int uploadID);
213 void _daveConstructEndUpload(PDU* p, int uploadID);
214 
215 int daveGetOrderCode(daveConnection* dc, char* buf);
216 int daveReadManyBytes(daveConnection* dc, int area, int DBnum, int start, int len, void* buffer);
217 int daveWriteManyBytes(daveConnection* dc, int area, int DB, int start, int len, void* buffer);
218 int daveReadBits(daveConnection* dc, int area, int DB, int start, int len, void* buffer);
219 int daveWriteBits(daveConnection* dc, int area, int DB, int start, int len, void* buffer);
220 
221 int daveReadSZL(daveConnection* dc, int ID, int index, void* buf, int buflen);
222 int daveListBlocksOfType(daveConnection* dc, ubyte type, daveBlockEntry* buf);
223 int daveListBlocks(daveConnection* dc, daveBlockTypeEntry* buf);
224 int initUpload(daveConnection* dc, char blockType, int blockNr, int* uploadID);
225 int doUpload(daveConnection* dc, int* more, ubyte** buffer, int* len, int uploadID);
226 int endUpload(daveConnection* dc, int uploadID);
227 int daveGetProgramBlock(daveConnection* dc, int blockType, int number, char* buffer, int* length);
228 int daveStop(daveConnection* dc);
229 int daveStart(daveConnection* dc);
230 int daveCopyRAMtoROM(daveConnection* dc);
231 int daveForce200(daveConnection* dc, int area, int start, int val);
232 void davePrepareReadRequest(daveConnection* dc, PDU* p);
233 void daveAddVarToReadRequest(PDU* p, int area, int DBnum, int start, int bytes);
234 int daveExecReadRequest(daveConnection* dc, PDU* p, daveResultSet* rl);
235 int daveUseResult(daveConnection* dc, daveResultSet* rl, int n);
236 void daveFreeResults(daveResultSet* rl);
237 void daveAddBitVarToReadRequest(PDU* p, int area, int DBnum, int start, int byteCount);
238 void davePrepareWriteRequest(daveConnection* dc, PDU* p);
239 void daveAddVarToWriteRequest(PDU* p, int area, int DBnum, int start, int bytes, void* buffer);
240 void daveAddBitVarToWriteRequest(PDU* p, int area, int DBnum, int start, int byteCount, void* buffer);
241 int daveExecWriteRequest(daveConnection* dc, PDU* p, daveResultSet* rl);
242 int daveInitAdapter(daveInterface* di);
243 int daveConnectPLC(daveConnection* dc);
244 int daveDisconnectPLC(daveConnection* dc);
245 int daveDisconnectAdapter(daveInterface* di);
246 int daveListReachablePartners(daveInterface* di, char* buf);
247 void daveSetTimeout(daveInterface* di, int tmo);
248 int daveGetTimeout(daveInterface* di);
249 char* daveGetName(daveInterface* di);
250 int daveGetMPIAdr(daveConnection* dc);
251 int daveGetAnswLen(daveConnection* dc);
252 int daveGetMaxPDULen(daveConnection* dc);
253 //daveResultSet* daveNewResultSet(...);
254 
255 // FIX: void daveFree(void* dc);
256 
257 //PDU* daveNewPDU(...);
258 int daveGetErrorOfResult(daveResultSet*, int number);
259 int daveForceDisconnectIBH(daveInterface* di, int src, int dest, int mpi);
260 int daveResetIBH(daveInterface* di);
261 int daveGetProgramBlock(daveConnection* dc, int blockType, int number, char* buffer, int* length);
262 
263 int daveSetPLCTime(daveConnection* dc, ubyte* ts);
264 int daveSetPLCTimeToSystime(daveConnection* dc);
265 
266 char* daveStrerror(int code);
267 void daveStringCopy(char* intString, char* extString);
268 void daveSetDebug(int nDebug);
269 int daveGetDebug();
270 
271 /**
272  * Create a daveInterface structure.
273  *
274  * Params:
275  *  nfd = A _daveOSserialType
276  *  nname = Interface name
277  *  localMPI = The address used by your computer/adapter (only meaningful for MPI and PPI)
278  *  protocol = A constant specifying the protocol to be used on this interface
279  *  speed = A constant specifying the speed to be used on this interface. (only meaningful for MPI and Profibus)
280  */
281 daveInterface* daveNewInterface(_daveOSserialType nfd, const(char)* nname, int localMPI, int protocol, int speed);
282 
283 /**
284  * Setup a new connection structure using an initialized
285  * daveInterface and PLC's MPI address.
286  *
287  * Params:
288  *  di = A daveInterface
289  *  MPI = The address of the PLC (only meaningful for MPI and PPI).
290  *  rack = The rack the CPU is mounted in (normally 0, only meaningful for ISO over TCP).
291  *  slot = The slot number the CPU is mounted in (normally 2, only meaningful for ISO over TCP)
292  */
293 daveConnection* daveNewConnection(daveInterface* di, int MPI, int rack, int slot);
294 int daveGetResponse(daveConnection* dc);
295 int daveSendMessage(daveConnection* dc, PDU* p);
296 void _daveDumpPDU(PDU* p);
297 void _daveDump(char* name, ubyte* b, int len);
298 char* daveBlockName(ubyte bn);
299 char* daveAreaName(ubyte n);
300 
301 short daveSwapIed_16(short ff);
302 int daveSwapIed_32(int ff);
303 float toPLCfloat(float ff);
304 int daveToPLCfloat(float ff);