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