| gclib 339 Communications API for Galil controllers and PLCs |

All Data Structures Files Functions Variables Typedefs Macros Pages
gclibo.c
Go to the documentation of this file.
1
7 #include "gclibo.h"
8
9 #include <stdlib.h> //atoi, atof
10 #include <string.h> //strcpy
11 #include <stdio.h> //fopen
12 #include <math.h> //log()
13
14 #define G_USE_GCAPS
15
16 void GCALL GSleep(unsigned int timeout_ms)
17 {
18 GUtility(0, G_UTIL_SLEEP, &timeout_ms, 0);
19 }
20
21 GReturn GCALL GVersion(GCStringOut ver, GSize ver_len)
22 {
23 int str_len;
24 GReturn rc;
25 if ((rc = GUtility(0, G_UTIL_VERSION, ver, &ver_len)) != G_NO_ERROR)
26 return rc;
27
28 #ifdef G_USE_GCAPS
29 str_len = strlen(ver) + 1;
30 ver_len -= str_len;
31 if (ver_len > 0
32 && GUtility(0, G_UTIL_GCAPS_VERSION, ver + str_len, &ver_len) == G_NO_ERROR)
33 {
34 ver[str_len - 1] = ' '; //add a delimiter
35 }
36 #endif
37
38 return rc;
39 }
40
41 GReturn GCALL GInfo(GCon g, GCStringOut info, GSize info_len)
42 {
43 return GUtility(g, G_UTIL_INFO, info, &info_len);
44 }
45
46 GReturn GCALL GAddresses(GCStringOut addresses, GSize addresses_len)
47 {
48 #ifdef G_USE_GCAPS
49 GReturn rc;
50 if (G_NO_ERROR == (rc = GUtility(0, G_UTIL_GCAPS_ADDRESSES, addresses, &addresses_len)))
51 return rc;
52 #endif
53
54 return GUtility(0, G_UTIL_ADDRESSES, addresses, &addresses_len);
55 }
56
57 GReturn GCALL GTimeout(GCon g, short timeout_ms)
58 {
59 return GUtility(g, G_UTIL_TIMEOUT_OVERRIDE, &timeout_ms, 0);
60 }
61
62 GReturn GCALL GAssign(char* ip, char* mac)
63 {
64 #ifdef G_USE_GCAPS
65 GReturn rc;
66 if (G_NO_ERROR == (rc = GUtility(0, G_UTIL_GCAPS_ASSIGN, ip, mac)))
67 return rc;
68 #endif
69
70 return GUtility(0, G_UTIL_ASSIGN, ip, mac);
71 }
72
73 GReturn GCALL GIpRequests(GCStringOut requests, GSize requests_len)
74 {
75 #ifdef G_USE_GCAPS
76 GReturn rc;
77 if (G_NO_ERROR == (rc = GUtility(0, G_UTIL_GCAPS_IPREQUEST, requests, &requests_len)))
78 return rc;
79 #endif
80
81 return GUtility(0, G_UTIL_IPREQUEST, requests, &requests_len);
82 }
83
84 GReturn GCALL GCmd(GCon g, GCStringIn command)
85 {
86 char buf[G_SMALL_BUFFER]; //response usually brief, e.g. :
87 GSize read;
88 return GCommand(g, command, buf, G_SMALL_BUFFER, &read);
89 }
90
91 GReturn GCALL GCmdT(GCon g, GCStringIn command, GCStringOut trimmed_response, GSize response_len, GCStringOut* front)
92 {
93 GSize read;
94 GReturn rc;
95 int i;
96 char c;
97 if ((rc = GCommand(g, command, trimmed_response, response_len, &read)) != G_NO_ERROR)
98 return rc;
99 //if here, the data is already null-terminated, just trim.
100 for (i = read - 1; i >= 0; i--) //read does NOT include null terminator.
101 {
102 c = trimmed_response[i];
103 if ((c == ':') || (c == '\n') || (c == '\r'))
104 trimmed_response[i] = 0; //trim it
105 else
106 break; //we hit non-trimmable data, bail out.
107 }
108
109 if (front) //null to skip "trim" on front.
110 {
111 *front = trimmed_response;
112 i = 0;
113 do
114 {
115 c = trimmed_response[i++];
116 if (c == ' ')
117 (*front)++;
118 else
119 break;
120 } while (1); //exit will be any non-space, including null terminator
121 }
122
123 return G_NO_ERROR;
124 }
125
126 GReturn GCALL GCmdI(GCon g, GCStringIn command, int* value)
127 {
128 char buf[G_SMALL_BUFFER]; //response should be ~19 chars
129 GSize read;
130 GReturn rc;
131 if ((rc = GCommand(g, command, buf, G_SMALL_BUFFER, &read)) != G_NO_ERROR)
132 return rc;
133 *value = atoi(buf);
134 return G_NO_ERROR;
135 }
136
137 GReturn GCALL GCmdD(GCon g, GCStringIn command, double* value)
138 {
139 char buf[G_SMALL_BUFFER]; //response should be ~19 chars
140 GSize read;
141 GReturn rc;
142 if ((rc = GCommand(g, command, buf, G_SMALL_BUFFER, &read)) != G_NO_ERROR)
143 return rc;
144 *value = atof(buf);
145 return G_NO_ERROR;
146 }
147
148 GReturn GCALL GMotionComplete(GCon g, GCStringIn axes)
149 {
150
151 char buf[G_SMALL_BUFFER]; //response should be ~19 chars.
152 char cmd[] = "MG_BGm"; //command for polling the axis' motion status, m is a place holder replaced below.
153 GSize read;
154 GReturn rc;
155 GSize i = 0; //C, not C++
156 GSize len = strlen(axes);
157
158 for (i = 0; i < len; i++) //iterate through all chars in axes
159 {
160 cmd[5] = axes[i]; //set the axis
161 poll:
162 if ((rc = GCommand(g, cmd, buf, G_SMALL_BUFFER, &read)) != G_NO_ERROR)
163 return rc;
164 if (atoi(buf))
165 {
166 GSleep(POLLINGINTERVAL);
167 goto poll;
168 }
169 }// for
170
171 return G_NO_ERROR;
172 }
173
174 GReturn GCALL GRecordRate(GCon g, double period_ms)
175 {
176 char buf[G_SMALL_BUFFER];
177 double dt;
178 double period_arg;
179
180 if (period_ms == 0) //turn off
181 return GCmd(g, "DR 0");
182
183 if (GCmdD(g, "TM?", &dt) == G_NO_ERROR)
184 {
185 dt /= 1024.0; //ms per controller sample
186 if (!dt) dt = 1; //don't want to divide by zero below
187 }
188 else
189 {
190 dt = 0.9765625; //RIO doesn't have TM
191 }
192
193 period_arg = period_ms / dt; //data record specified in samples between records
194
195 if (GCmdT(g, "\x12\x16", buf, sizeof(buf), 0) == G_NO_ERROR) //Revision string, ^R^V
196 {
197 if (strstr(buf, "DMC18")) //PCI controller
198 period_arg = log(period_arg) / log(2.0); //PCI DR arg is 2^n.
199 else if ((strstr(buf, "DMC40") != NULL) //4000
200 || (strstr(buf, "DMC500") != NULL) //50000
201 || (strstr(buf, "RIO") != NULL)) // RIO
202 {
203 if (period_arg < 2) period_arg = 2; //lowest non-zero DR
204 }
205 else if ((strstr(buf, "DMC41") != NULL) || (strstr(buf, "DMC21") != NULL)) //4103, 2103
206 {
207 if (period_arg < 8) period_arg = 8; //lowest non-zero DR
208 }
209 else if ((strstr(buf, "DMC3") != NULL)) //30010, 31010
210 {
211 if (period_arg < 4) period_arg = 4; //lowest non-zero DR
212 }
213 }
214
215 sprintf(buf, "DR %d", (int)period_arg);
216 return GCmd(g, buf);
217 }
218
219 GReturn GCALL GProgramDownloadFile(GCon g, GCStringIn file_path, GCStringIn preprocessor)
220 {
221 FILE *file;
222 long file_size;
223 char* program_buffer;
224 GReturn rc = G_NO_ERROR;
225
226 if (!(file = fopen(file_path, "rb"))) //open file for reading, binary mode
227 return G_BAD_FILE;
228
229 fseek(file, 0, SEEK_END); //find end of file
230 file_size = ftell(file); //add one to null terminate below
231 rewind(file);
232
233 if (file_size) //don't malloc 0.
234 {
235
236 if (!(program_buffer = malloc(file_size + 1))) //allocate memory for the data, +1 for null termination below
237 {
238 fclose(file);
239 return G_BAD_FULL_MEMORY;
240 }
241
242 if (file_size != fread(program_buffer, 1, file_size, file))
243 {
244 fclose(file);
245 free(program_buffer); //free memory
246 return G_BAD_FILE;
247 }
248 program_buffer[file_size] = 0; //null terminate, malloc was one byte larger for this
249 }
250 else
251 {
252 program_buffer = ""; //nullstring
253 }
254
255 fclose(file); //done with file, close it
256
257 rc = GProgramDownload(g, program_buffer, preprocessor); //call the gclib downloader
258 if (file_size) free(program_buffer); //free memory
259 return rc;
260 }
261
262 GReturn GCALL GProgramUploadFile(GCon g, GCStringIn file_path)
263 {
264 FILE *file;
265 GReturn rc = G_NO_ERROR;
266 char* program_buffer;
267 long file_size;
268
269 if (!(file = fopen(file_path, "wb"))) //open file for writing, binary mode
270 return G_BAD_FILE;
271
272 if (!(program_buffer = malloc(MAXPROG))) //allocate memory for the data
273 {
274 fclose(file);
275 return G_BAD_FULL_MEMORY;
276 }
277
278 if ((rc = GProgramUpload(g, program_buffer, MAXPROG)) == G_NO_ERROR)
279 {
280 file_size = strlen(program_buffer);
281 if (file_size != fwrite(program_buffer, 1, file_size, file))
282 rc = G_BAD_FILE;
283 }
284
285 fclose(file);
286 free(program_buffer);
287 return rc;
288 }
289
290
291 void GCALL GError(GReturn rc, GCStringOut error, GSize error_len)
292 {
293 char* error_message;
294
295 switch (rc)
296 {
297 case G_NO_ERROR:
298 error_message = G_NO_ERROR_S;
299 break;
300
301 case G_GCLIB_ERROR:
302 error_message = G_GCLIB_ERROR_S;
303 break;
304
305 case G_GCLIB_UTILITY_ERROR:
306 error_message = G_GCLIB_UTILITY_ERROR_S;
307 break;
308
309 case G_GCLIB_UTILITY_IP_TAKEN:
310 error_message = G_GCLIB_UTILITY_IP_TAKEN_S;
311 break;
312
313 case G_GCLIB_NON_BLOCKING_READ_EMPTY:
314 error_message = G_GCLIB_NON_BLOCKING_READ_EMPTY_S;
315 break;
316
317 case G_TIMEOUT:
318 error_message = G_TIMEOUT_S;
319 break;
320
321 case G_OPEN_ERROR:
322 error_message = G_OPEN_ERROR_S;
323 break;
324
325 case G_COMMAND_CALLED_WITH_ILLEGAL_COMMAND:
326 error_message = G_COMMAND_CALLED_WITH_ILLEGAL_COMMAND_S;
327 break;
328
329 case G_DATA_RECORD_ERROR:
330 error_message = G_DATA_RECORD_ERROR_S;
331 break;
332
333 case G_UNSUPPORTED_FUNCTION:
334 error_message = G_UNSUPPORTED_FUNCTION_S;
335 break;
336
337 case G_BAD_ADDRESS:
338 error_message = G_BAD_ADDRESS_S;
339 break;
340
341 case G_FIRMWARE_LOAD_NOT_SUPPORTED:
342 error_message = G_FIRMWARE_LOAD_NOT_SUPPORTED_S;
343 break;
344
345 case G_ARRAY_NOT_DIMENSIONED:
346 error_message = G_ARRAY_NOT_DIMENSIONED_S;
347 break;
348
349 case G_ILLEGAL_DATA_IN_PROGRAM:
350 error_message = G_ILLEGAL_DATA_IN_PROGRAM_S;
351 break;
352
353 case G_UNABLE_TO_COMPRESS_PROGRAM_TO_FIT:
354 error_message = G_UNABLE_TO_COMPRESS_PROGRAM_TO_FIT_S;
355 break;
356
357 case G_INVALID_PREPROCESSOR_OPTIONS:
358 error_message = G_INVALID_PREPROCESSOR_OPTIONS_S;
359 break;
360
361 case G_BAD_RESPONSE_QUESTION_MARK:
362 error_message = G_BAD_RESPONSE_QUESTION_MARK_S;
363 break;
364
365 case G_BAD_VALUE_RANGE:
366 error_message = G_BAD_VALUE_RANGE_S;
367 break;
368
369 case G_BAD_FULL_MEMORY:
370 error_message = G_BAD_FULL_MEMORY_S;
371 break;
372
373 case G_BAD_LOST_DATA:
374 error_message = G_BAD_LOST_DATA_S;
375 break;
376
377 case G_BAD_FILE:
378 error_message = G_BAD_FILE_S;
379 break;
380
381 case G_GCAPS_OPEN_ERROR:
382 error_message = G_GCAPS_OPEN_ERROR_S;
383 break;
384
385 default:
386 error_message = "internal error";
387 break;
388 }
389
390 strncpy(error, error_message, error_len);
391 error[error_len - 1] = 0; //ensure null termination
392 }
GSleep
void GCALL GSleep(unsigned int timeout_ms)
Uses GUtility() and G_UTIL_SLEEP to provide a blocking sleep call which can be useful for timing-base...
Definition: gclibo.c:16
G_SMALL_BUFFER
#define G_SMALL_BUFFER
Most reads/writes to Galil are small. This value will easily hold most, e.g. TH, TZ, etc.
Definition: gclib.h:59
GInfo
GReturn GCALL GInfo(GCon g, GCStringOut info, GSize info_len)
Uses GUtility() and G_UTIL_INFO to provide a useful connection string.
Definition: gclibo.c:41
GSize
unsigned int GSize
Size of buffers, etc.
Definition: gclib.h:64
G_UTIL_IPREQUEST
#define G_UTIL_IPREQUEST
GUtility(), get a list of hardware requesting IPs.
Definition: gclib.h:48
G_UTIL_GCAPS_IPREQUEST
#define G_UTIL_GCAPS_IPREQUEST
GUtility(), get a list of hardware requesting IPs from the gcaps server.
Definition: gclib.h:55
G_UNABLE_TO_COMPRESS_PROGRAM_TO_FIT
#define G_UNABLE_TO_COMPRESS_PROGRAM_TO_FIT
Program preprocessor could not compress the program within the user's constraints.
Definition: gclib_errors.h:51
GCmdT
GReturn GCALL GCmdT(GCon g, GCStringIn command, GCStringOut trimmed_response, GSize response_len, GCStringOut *front)
Wrapper around GCommand that trims the response.
Definition: gclibo.c:91
MAXPROG
#define MAXPROG
Maximum size for a program.
Definition: gclibo.h:36
G_COMMAND_CALLED_WITH_ILLEGAL_COMMAND
#define G_COMMAND_CALLED_WITH_ILLEGAL_COMMAND
GCommand() was called with an illegal command, e.g. ED, DL or QD.
Definition: gclib_errors.h:33
G_DATA_RECORD_ERROR
#define G_DATA_RECORD_ERROR
Data record error, e.g. DR attempted on serial connection.
Definition: gclib_errors.h:36
G_OPEN_ERROR
#define G_OPEN_ERROR
Device could not be opened. E.G. Serial port or PCI device already open.
Definition: gclib_errors.h:27
G_ILLEGAL_DATA_IN_PROGRAM
#define G_ILLEGAL_DATA_IN_PROGRAM
Data to download not valid, e.g. \ in data.
Definition: gclib_errors.h:48
GProgramUploadFile
GReturn GCALL GProgramUploadFile(GCon g, GCStringIn file_path)
Program upload to file.
Definition: gclibo.c:262
G_BAD_RESPONSE_QUESTION_MARK
#define G_BAD_RESPONSE_QUESTION_MARK
Operation received a ?, indicating controller has a TC error.
Definition: gclib_errors.h:54
GUtility
GCLIB_DLL_EXPORTED GReturn GCALL GUtility(GCon g, GOption request, GMemory memory1, GMemory memory2)
Provides read/write access to driver settings and convenience features based on the request variable...
G_ARRAY_NOT_DIMENSIONED
#define G_ARRAY_NOT_DIMENSIONED
Array operation was called on an array that was not in the controller's array table, see LA command.
Definition: gclib_errors.h:45
G_TIMEOUT
#define G_TIMEOUT
Operation timed out. Timeout is set by the –timeout option in GOpen() and can be overriden by GSetti...
Definition: gclib_errors.h:24
POLLINGINTERVAL
#define POLLINGINTERVAL
Interval, in miliseconds, for polling commands, e.g. GMotionComplete().
Definition: gclibo.h:38
GCmdI
GReturn GCALL GCmdI(GCon g, GCStringIn command, int *value)
Wrapper around GCommand that provides the return value of a command parsed into an int...
Definition: gclibo.c:126
G_GCLIB_UTILITY_ERROR
#define G_GCLIB_UTILITY_ERROR
An invalid request value was specified to GUtility.
Definition: gclib_errors.h:15
GMotionComplete
GReturn GCALL GMotionComplete(GCon g, GCStringIn axes)
Blocking call that returns once all axes specified have completed their motion.
Definition: gclibo.c:148
G_UTIL_SLEEP
#define G_UTIL_SLEEP
GUtility(), specify an interval to sleep.
Definition: gclib.h:46
G_GCAPS_OPEN_ERROR
#define G_GCAPS_OPEN_ERROR
gcaps connection couldn't open. Server is not running or is not reachable.
Definition: gclib_errors.h:72
G_UNSUPPORTED_FUNCTION
#define G_UNSUPPORTED_FUNCTION
Function cannot be called on this bus. E.G. GInterrupt() on serial.
Definition: gclib_errors.h:39
GCmd
GReturn GCALL GCmd(GCon g, GCStringIn command)
Wrapper around GCommand for use when the return value is not desired.
Definition: gclibo.c:84
G_GCLIB_ERROR
#define G_GCLIB_ERROR
General library error. Indicates internal API caught an unexpected error. Contact Galil support if th...
Definition: gclib_errors.h:12
G_UTIL_ADDRESSES
#define G_UTIL_ADDRESSES
GUtility(), get a list of available connections.
Definition: gclib.h:47
GVersion
GReturn GCALL GVersion(GCStringOut ver, GSize ver_len)
Uses GUtility(), G_UTIL_VERSION and G_UTIL_GCAPS_VERSION to provide the library and gcaps version num...
Definition: gclibo.c:21
G_UTIL_INFO
#define G_UTIL_INFO
GUtility(), get a connection info string.
Definition: gclib.h:45
GCon
void * GCon
Connection handle. Unique for each connection in process. Assigned a non-zero value in GOpen()...
Definition: gclib.h:63
G_UTIL_TIMEOUT_OVERRIDE
#define G_UTIL_TIMEOUT_OVERRIDE
GUtility(), read/write access to timeout override.
Definition: gclib.h:42
G_UTIL_GCAPS_VERSION
#define G_UTIL_GCAPS_VERSION
GUtility(), get the version of the gcaps server.
Definition: gclib.h:52
GError
void GCALL GError(GReturn rc, GCStringOut error, GSize error_len)
Provides a human-readable description string for return codes.
Definition: gclibo.c:291
GProgramDownload
GCLIB_DLL_EXPORTED GReturn GCALL GProgramDownload(GCon g, GCStringIn program, GCStringIn preprocessor)
Downloads a program to the controller's program buffer.
GCommand
GCLIB_DLL_EXPORTED GReturn GCALL GCommand(GCon g, GCStringIn command, GBufOut buffer, GSize buffer_len, GSize *bytes_returned)
Performs a command-and-response transaction on the connection.
GProgramUpload
GCLIB_DLL_EXPORTED GReturn GCALL GProgramUpload(GCon g, GBufOut buffer, GSize buffer_len)
Uploads a program from the controller's program buffer.
GTimeout
GReturn GCALL GTimeout(GCon g, short timeout_ms)
Uses GUtility() and G_UTIL_TIMEOUT_OVERRIDE to set the library timeout.
Definition: gclibo.c:57
GReturn
int GReturn
Every function returns a value of type GReturn. See gclib_errors.h for possible values.
Definition: gclib.h:62
G_GCLIB_UTILITY_IP_TAKEN
#define G_GCLIB_UTILITY_IP_TAKEN
The IP cannot be assigned because ping returned a reply.
Definition: gclib_errors.h:18
GIpRequests
GReturn GCALL GIpRequests(GCStringOut requests, GSize requests_len)
Uses GUtility(), G_UTIL_GCAPS_IPREQUEST or G_UTIL_IPREQUEST to provide a list of all Galil controller...
Definition: gclibo.c:73
G_INVALID_PREPROCESSOR_OPTIONS
#define G_INVALID_PREPROCESSOR_OPTIONS
GProgramDownload was called with a bad preprocessor directive.
Definition: gclib_errors.h:30
G_BAD_LOST_DATA
#define G_BAD_LOST_DATA
Lost data, e.g. GCommand() response buffer was too small for the controller's response.
Definition: gclib_errors.h:63
G_UTIL_VERSION
#define G_UTIL_VERSION
GUtility(), get a library version string.
Definition: gclib.h:44
G_BAD_FULL_MEMORY
#define G_BAD_FULL_MEMORY
Not enough memory for an operation, e.g. all connections allowed for a process already taken...
Definition: gclib_errors.h:60
G_BAD_VALUE_RANGE
#define G_BAD_VALUE_RANGE
Bad value or range, e.g. GCon g variable passed to function was bad.
Definition: gclib_errors.h:57
GCStringIn
const char * GCStringIn
C-string input to the library. Implies null-termination.
Definition: gclib.h:67
G_NO_ERROR
#define G_NO_ERROR
Return value if function succeeded.
Definition: gclib_errors.h:9
G_GCLIB_NON_BLOCKING_READ_EMPTY
#define G_GCLIB_NON_BLOCKING_READ_EMPTY
GMessage, GInterrupt, and GRecord can be called with a zero timeout. If there wasn't data waiting in ...
Definition: gclib_errors.h:21
G_FIRMWARE_LOAD_NOT_SUPPORTED
#define G_FIRMWARE_LOAD_NOT_SUPPORTED
Firmware is not supported on this bus, e.g. Ethernet for the DMC-21x3 series.
Definition: gclib_errors.h:42
GCStringOut
char * GCStringOut
C-string output from the library. Implies null-termination.
Definition: gclib.h:66
GAddresses
GReturn GCALL GAddresses(GCStringOut addresses, GSize addresses_len)
Uses GUtility(), G_UTIL_GCAPS_ADDRESSES or G_UTIL_ADDRESSES to provide a listing of all available con...
Definition: gclibo.c:46
GAssign
GReturn GCALL GAssign(char *ip, char *mac)
Uses GUtility(), G_UTIL_GCAPS_ASSIGN or G_UTIL_ASSIGN to assign an IP address over the Ethernet to a ...
Definition: gclibo.c:62
GCmdD
GReturn GCALL GCmdD(GCon g, GCStringIn command, double *value)
Wrapper around GCommand that provides the return value of a command parsed into a double...
Definition: gclibo.c:137
GCALL
#define GCALL
Specify calling convention for Windows.
Definition: gclib.h:24
G_UTIL_GCAPS_ADDRESSES
#define G_UTIL_GCAPS_ADDRESSES
GUtility(), get a list of available connections from the gcaps server.
Definition: gclib.h:54
G_BAD_ADDRESS
#define G_BAD_ADDRESS
Bad address.
Definition: gclib_errors.h:69
GProgramDownloadFile
GReturn GCALL GProgramDownloadFile(GCon g, GCStringIn file_path, GCStringIn preprocessor)
Program download from file.
Definition: gclibo.c:219
GRecordRate
GReturn GCALL GRecordRate(GCon g, double period_ms)
Sets the asynchronous data record to a user-specified period via DR.
Definition: gclibo.c:174
G_BAD_FILE
#define G_BAD_FILE
Bad file path, bad file contents, or bad write.
Definition: gclib_errors.h:66
gclibo.h
G_UTIL_ASSIGN
#define G_UTIL_ASSIGN
GUtility(), assign IP addresses via Boot-P reply.
Definition: gclib.h:49
G_UTIL_GCAPS_ASSIGN
#define G_UTIL_GCAPS_ASSIGN
GUtility(), assign IP addresses via Boot-P reply from the gcaps server.
Definition: gclib.h:56