gclibo.c

Go to the documentation of this file.
00001 
00007 #include "gclibo.h"
00008 
00009 void GCALL GSleep(unsigned int timeout_ms)
00010 {
00011   GUtility(0, G_UTIL_SLEEP, &timeout_ms, 0);
00012 }
00013 
00014 GReturn GCALL GVersion(GCStringOut ver, GSize ver_len)
00015 {
00016   return GUtility(0, G_UTIL_VERSION, ver, &ver_len);
00017 }
00018 
00019 GReturn GCALL GInfo(GCon g, GCStringOut info, GSize info_len)
00020 {
00021   return GUtility(g, G_UTIL_INFO, info, &info_len);
00022 }
00023 
00024 GReturn GCALL GAddresses(GCStringOut addresses, GSize addresses_len)
00025 {
00026   return GUtility(0, G_UTIL_ADDRESSES, addresses, &addresses_len);
00027 }
00028 
00029 GReturn GCALL GTimeout(GCon g, short timeout_ms)
00030 {
00031   return GUtility(g, G_UTIL_TIMEOUT_OVERRIDE, &timeout_ms, 0);
00032 }
00033 
00034 GReturn GCALL GAssign(char* ip, char* mac)
00035 {
00036   return GUtility(0, G_UTIL_ASSIGN, ip, mac);
00037 }
00038 
00039 GReturn GCALL GIpRequests(GCStringOut requests, GSize requests_len)
00040 {
00041   return GUtility(0, G_UTIL_IPREQUEST, requests, &requests_len);
00042 }
00043 
00044 GReturn GCALL GCmd(GCon g, GCStringIn command)
00045 {
00046   char buf[SMALLBUF]; //response usually brief, e.g. :
00047   GSize read;
00048   return GCommand(g, command, buf, SMALLBUF, &read);
00049 }
00050 
00051 GReturn GCALL GCmdT(GCon g, GCStringIn command, GCStringOut trimmed_response, GSize response_len, GCStringOut* front)
00052 {
00053   GSize read;
00054   GReturn rc;
00055   int i;
00056   char c;
00057   if ((rc = GCommand(g, command, trimmed_response, response_len, &read)) != G_NO_ERROR)
00058     return rc;
00059   //if here, the data is already null-terminated, just trim.
00060   for (i = read - 1; i >= 0; i--) //read does NOT include null terminator.
00061   {
00062     c = trimmed_response[i];
00063     if ((c == ':') || (c == '\n') || (c == '\r'))
00064       trimmed_response[i] = 0; //trim it
00065     else
00066       break; //we hit non-trimmable data, bail out.
00067   }
00068 
00069   if (front) //null to skip "trim" on front.
00070   {
00071     *front = trimmed_response;
00072     i = 0;
00073     do
00074     {
00075       c = trimmed_response[i++];
00076       if (c == ' ')
00077         (*front)++;
00078       else
00079         break;
00080     } while (1); //exit will be any non-space, including null terminator
00081   }
00082 
00083   return G_NO_ERROR;
00084 }
00085 
00086 GReturn GCALL GCmdI(GCon g, GCStringIn command, int* value)
00087 {
00088   char buf[SMALLBUF]; //response should be ~19 chars
00089   GSize read;
00090   GReturn rc;
00091   if ((rc = GCommand(g, command, buf, SMALLBUF, &read)) != G_NO_ERROR)
00092     return rc;
00093   *value = atoi(buf);
00094   return G_NO_ERROR;
00095 }
00096 
00097 GReturn GCALL GCmdD(GCon g, GCStringIn command, double* value)
00098 {
00099   char buf[SMALLBUF]; //response should be ~19 chars
00100   GSize read;
00101   GReturn rc;
00102   if ((rc = GCommand(g, command, buf, SMALLBUF, &read)) != G_NO_ERROR)
00103     return rc;
00104   *value = atof(buf);
00105   return G_NO_ERROR;
00106 }
00107 
00108 GReturn GCALL GMotionComplete(GCon g, GCStringIn axes)
00109 {
00110 
00111   char buf[SMALLBUF]; //response should be ~19 chars.
00112   char cmd[] = "MG_BGm"; //command for polling the axis' motion status, m is a place holder replaced below.
00113   GSize read;
00114   GReturn rc;
00115   GSize i = 0; //C, not C++
00116   GSize len = strlen(axes);
00117 
00118   for (i = 0; i < len; i++) //iterate through all chars in axes
00119   {
00120     cmd[5] = axes[i]; //set the axis
00121   poll:
00122     if ((rc = GCommand(g, cmd, buf, SMALLBUF, &read)) != G_NO_ERROR)
00123       return rc;
00124     if (atoi(buf))
00125     {
00126       GSleep(POLLINGINTERVAL);
00127       goto poll;
00128     }
00129   }// for
00130 
00131   return G_NO_ERROR;
00132 }
00133 
00134 GReturn GCALL GRecordRate(GCon g, double period_ms)
00135 {
00136   char buf[SMALLBUF];
00137   double dt;
00138   double period_arg;
00139 
00140   if (period_ms == 0) //turn off
00141     return GCmd(g, "DR 0");
00142 
00143   if (GCmdD(g, "TM?", &dt) == G_NO_ERROR)
00144   {
00145     dt /= 1024.0; //ms per controller sample
00146     if (!dt) dt = 1; //don't want to divide by zero below
00147   }
00148   else
00149   {
00150     dt = 0.9765625; //RIO doesn't have TM
00151   }
00152 
00153   period_arg = period_ms / dt; //data record specified in samples between records
00154 
00155   if (GCmdT(g, "\x12\x16", buf, sizeof(buf), 0) == G_NO_ERROR) //Revision string, ^R^V
00156   {
00157     if (strstr(buf, "DMC18")) //PCI controller
00158       period_arg = log(period_arg) / log(2.0); //PCI DR arg is 2^n.
00159     else if ((strstr(buf, "DMC40") != NULL) //4000
00160       || (strstr(buf, "DMC500") != NULL) //50000
00161       || (strstr(buf, "RIO") != NULL)) // RIO
00162     {
00163       if (period_arg < 2) period_arg = 2; //lowest non-zero DR
00164     }
00165     else if ((strstr(buf, "DMC41") != NULL) || (strstr(buf, "DMC21") != NULL)) //4103, 2103
00166     {
00167       if (period_arg < 8) period_arg = 8; //lowest non-zero DR
00168     }
00169     else if ((strstr(buf, "DMC3") != NULL)) //30010, 31010
00170     {
00171       if (period_arg < 4) period_arg = 4; //lowest non-zero DR
00172     }
00173   }
00174   
00175   sprintf(buf, "DR %d", (int)period_arg);
00176   return GCmd(g, buf);
00177 }
00178 
00179 GReturn GCALL GProgramDownloadFile(GCon g, GCStringIn file_path, GCStringIn preprocessor)
00180 {
00181   FILE *file;
00182   long file_size;
00183   char* program_buffer;
00184   GReturn rc = G_NO_ERROR;
00185 
00186   if (!(file = fopen(file_path, "rb"))) //open file for reading, binary mode
00187     return G_BAD_FILE;
00188 
00189   fseek(file, 0, SEEK_END); //find end of file
00190   file_size = ftell(file); //add one to null terminate below
00191   rewind(file);
00192 
00193   if (file_size) //don't malloc 0.
00194   {
00195 
00196     if (!(program_buffer = malloc(file_size + 1))) //allocate memory for the data, +1 for null termination below
00197     {
00198       fclose(file);
00199       return G_BAD_FULL_MEMORY;
00200     }
00201 
00202     if (file_size != fread(program_buffer, 1, file_size, file))
00203     {
00204       fclose(file);
00205       free(program_buffer); //free memory
00206       return G_BAD_FILE;
00207     }
00208     program_buffer[file_size] = 0; //null terminate, malloc was one byte larger for this
00209   }
00210   else
00211   {
00212     program_buffer = ""; //nullstring
00213   }
00214 
00215   fclose(file); //done with file, close it
00216 
00217   rc = GProgramDownload(g, program_buffer, preprocessor); //call the gclib downloader
00218   if (file_size) free(program_buffer); //free memory
00219   return rc;
00220 }
00221 
00222 GReturn GCALL GProgramUploadFile(GCon g, GCStringIn file_path)
00223 {
00224   FILE *file;
00225   GReturn rc = G_NO_ERROR;
00226   char* program_buffer;
00227   long file_size;
00228 
00229   if (!(file = fopen(file_path, "wb"))) //open file for writing, binary mode
00230     return G_BAD_FILE;
00231 
00232   if (!(program_buffer = malloc(MAXPROG))) //allocate memory for the data
00233   {
00234     fclose(file);
00235     return G_BAD_FULL_MEMORY;
00236   }
00237 
00238   if ((rc = GProgramUpload(g, program_buffer, MAXPROG)) == G_NO_ERROR)
00239   {
00240     file_size = strlen(program_buffer);
00241     if (file_size != fwrite(program_buffer, 1, file_size, file))
00242       rc = G_BAD_FILE;
00243   }
00244 
00245   fclose(file);
00246   free(program_buffer);
00247   return rc;
00248 }
00249 
00250 
00251 void GCALL GError(GReturn rc, GCStringOut error, GSize error_len)
00252 {
00253   char* error_message;
00254 
00255   switch (rc)
00256   {
00257   case G_NO_ERROR:
00258     error_message = G_NO_ERROR_S;
00259     break;
00260 
00261   case G_GCLIB_ERROR:
00262     error_message = G_GCLIB_ERROR_S;
00263     break;
00264 
00265   case G_GCLIB_UTILITY_ERROR:
00266     error_message = G_GCLIB_UTILITY_ERROR_S;
00267     break;
00268 
00269   case G_GCLIB_UTILITY_IP_TAKEN:
00270     error_message = G_GCLIB_UTILITY_IP_TAKEN_S;
00271     break;
00272 
00273   case G_GCLIB_NON_BLOCKING_READ_EMPTY:
00274     error_message = G_GCLIB_NON_BLOCKING_READ_EMPTY_S;
00275     break;
00276 
00277   case G_TIMEOUT:
00278     error_message = G_TIMEOUT_S;
00279     break;
00280 
00281   case G_OPEN_ERROR:
00282     error_message = G_OPEN_ERROR_S;
00283     break;
00284 
00285   case G_COMMAND_CALLED_WITH_ILLEGAL_COMMAND:
00286     error_message = G_COMMAND_CALLED_WITH_ILLEGAL_COMMAND_S;
00287     break;
00288 
00289   case G_DATA_RECORD_ERROR:
00290     error_message = G_DATA_RECORD_ERROR_S;
00291     break;
00292 
00293   case G_UNSUPPORTED_FUNCTION:
00294     error_message = G_UNSUPPORTED_FUNCTION_S;
00295     break;
00296 
00297   case G_BAD_ADDRESS:
00298     error_message = G_BAD_ADDRESS_S;
00299     break;
00300 
00301   case G_FIRMWARE_LOAD_NOT_SUPPORTED:
00302     error_message = G_FIRMWARE_LOAD_NOT_SUPPORTED_S;
00303     break;
00304 
00305   case G_ARRAY_NOT_DIMENSIONED:
00306     error_message = G_ARRAY_NOT_DIMENSIONED_S;
00307     break;
00308 
00309   case G_ILLEGAL_DATA_IN_PROGRAM:
00310     error_message = G_ILLEGAL_DATA_IN_PROGRAM_S;
00311     break;
00312 
00313   case G_UNABLE_TO_COMPRESS_PROGRAM_TO_FIT:
00314     error_message = G_UNABLE_TO_COMPRESS_PROGRAM_TO_FIT_S;
00315     break;
00316 
00317   case G_INVALID_PREPROCESSOR_OPTIONS:
00318     error_message = G_INVALID_PREPROCESSOR_OPTIONS_S;
00319     break;
00320 
00321   case G_BAD_RESPONSE_QUESTION_MARK:
00322     error_message = G_BAD_RESPONSE_QUESTION_MARK_S;
00323     break;
00324 
00325   case G_BAD_VALUE_RANGE:
00326     error_message = G_BAD_VALUE_RANGE_S;
00327     break;
00328 
00329   case G_BAD_FULL_MEMORY:
00330     error_message = G_BAD_FULL_MEMORY_S;
00331     break;
00332 
00333   case G_BAD_LOST_DATA:
00334     error_message = G_BAD_LOST_DATA_S;
00335     break;
00336 
00337   case G_BAD_FILE:
00338     error_message = G_BAD_FILE_S;
00339     break;
00340 
00341   default:
00342     error_message = "internal error";
00343     break;
00344   }
00345 
00346   strncpy(error, error_message, error_len);
00347   error[error_len - 1] = 0; //ensure null termination
00348 }