libpdv.c

Go to the documentation of this file.
00001 
00002 /* #pragma ident "@(#)libpdv.c  1.398 03/15/07 EDT" */
00003 
00277 #include "edtinc.h"
00278 
00279 #include <math.h>
00280 /* #define NDEBUG  here or with make -DNDEBUG to turn off assert */
00281 #include <assert.h>
00282 
00283 #ifdef _NT_
00284 #define strncasecmp strnicmp
00285 #endif
00286 
00287 /* shorthand debug level */
00288 #define PDVWARN PDVLIB_MSG_WARNING
00289 #define PDVFATAL PDVLIB_MSG_FATAL
00290 #define DBG1 PDVLIB_MSG_INFO_1
00291 #define DBG2 PDVLIB_MSG_INFO_2
00292 
00293 int Pdv_debug = 0;
00294 int     Smd_type = NOT_SET;
00295 int     Smd_rate = NOT_SET;
00296 
00297 /*
00298  * library routines
00299  */
00300 
00301 
00302 #define PDV_DEPENDENT(pdv_p) ((pdv_p)->dd_p)
00303 
00304 static void
00305         debug_print_serial_command(char *cmd);
00306 static void
00307         send_serial_binary_cmd(PdvDev * pdv_p, char *hexstr, int value);
00308 
00309 static void pdv_trigger_specinst(PdvDev * pdv_p);
00310 static void pdv_posttrigger_specinst(PdvDev * pdv_p);
00311 static int pdv_specinst_setparam(PdvDev * pdv_p, char cmd, u_long offset, u_long value);
00312 
00316 static int pdv_set_exposure_specinst(PdvDev * pdv_p, int value);
00317 static int pdv_set_gain_specinst(PdvDev * pdv_p, int value);
00318 static int pdv_set_exposure_adimec(PdvDev * pdv_p, int value);
00319 static int pdv_set_exposure_su320(PdvDev * pdv_p, int value);
00320 static int pdv_set_gain_adimec(PdvDev * pdv_p, int value);
00321 static int pdv_set_blacklevel_adimec(PdvDev * pdv_p, int value);
00322 static int pdv_set_exposure_smd(PdvDev * pdv_p, int value);
00323 static int pdv_set_exposure_timc1001pf(PdvDev * pdv_p, int value);
00324 static int pdv_set_exposure_ptm6710_1020(PdvDev * pdv_p, int value);
00325 static int pdv_set_gain_ptm6710_1020(PdvDev * pdv_p, int value);
00326 static int pdv_set_binning_generic(PdvDev * pdv_p, int value);
00327 static int pdv_set_gain_smd(PdvDev * pdv_p, int value);
00328 static int pdv_set_blacklevel_smd(PdvDev * pdv_p, int value);
00329 static int pdv_set_gain_hc8484(PdvDev * pdv_p, int value);
00332 static int pdv_specinst_serial_triggered(PdvDev * pdv_p);
00333 static void CheckSumMessage(unsigned char *msg);
00334 int     pdv_auto_set_timeout(PdvDev * pdv_p);
00335 static int isafloat(char *str);
00336 static int isdigits(char *str);
00337 static int isxdigits(char *str);
00338 static int update_int_from_serial(char **stat, int nstat, char *str, int *value);
00339 static int update_string_from_serial(char **stat, int nstat, char *str, char *value, int maxlen);
00340 static void update_hex_from_serial(char **stat, int nstat, char *str, int *value);
00341 static void update_2dig_from_serial(char **stat, int nstat, char *str, int *val1, int *val2);
00342 int     edt_get_rtimeout(PdvDev * pdv_p);
00343 static int pdv_update_from_kodak_i(PdvDev * pdv_p);
00344 
00345 static int pdv_update_from_atmel(PdvDev * pdv_p);
00346 static int pdv_update_from_hamamatsu(PdvDev * pdv_p);
00347 static int pdv_set_mode_atmel(PdvDev * pdv_p, char *mode);
00348 static int pdv_set_mode_hamamatsu(PdvDev * pdv_p, char *mode);
00349 
00350 static int pdv_set_exposure_timc1001pf(PdvDev * pdv_p, int value);
00351 
00352 int     pdv_query_serial(PdvDev * pdv_p, char *cmd, char **resp);
00353 
00354 /* from pdv_interlace.c */
00355 
00356 void    pdv_dmy_data(void *buf, int width, int height, int depth);
00357 void    pdv_alloc_tmpbuf(PdvDev * pdv_p);
00358 extern  pdv_process_inplace(PdvDev *pdv_p);
00359 int     pdv_update_size(PdvDev * pdv_p);
00360 
00361 static char *hex_to_str(char *resp, int n);
00362 
00363 #ifdef DOXYGEN_SHOW_UNDOC
00364 
00369 #endif
00370 
00430 PdvDev *
00431 pdv_open_channel(char *dev_name, int unit, int channel)
00432 {
00433     PdvDev *pdv_p;
00434     char    tmpname[64];
00435     Dependent *dd_p;
00436     static char *debug_env = NULL;
00437     int     level;
00438 
00439     if ((debug_env == NULL)
00440         && ((debug_env = (char *) getenv("PDVDEBUG")) != NULL)
00441         && *debug_env != '0')
00442     {
00443         Pdv_debug = atoi(debug_env);
00444         level = edt_msg_default_level();
00445         if (Pdv_debug > 0)
00446         {
00447             level |= DBG1;
00448             level |= DBG2;
00449         }
00450         edt_msg_set_level(edt_msg_default_handle(), level);
00451 
00452         edt_msg(DBG2, "environment DEBUG set to %d: enabling debug in pdvlib\n", Pdv_debug);
00453     }
00454 
00455     edt_msg(DBG2, "pdv_open_channel('%s', %d, %d)\n", dev_name ? dev_name : "NULL",
00456             unit, channel);
00457 
00458     if (dev_name == NULL)
00459         strcpy(tmpname, EDT_INTERFACE);
00460     else
00461         strcpy(tmpname, dev_name);
00462     if ((pdv_p = edt_open_channel(tmpname, unit, channel)) == NULL)
00463         return NULL;
00464 
00465 
00466     if (pdv_p->devid == PDVFOI_ID)
00467     {
00468 #ifdef _FOI_SUPPORTED
00469         edt_check_foi(pdv_p);
00470 #else
00471         edt_msg(PDVFATAL, "pdv_open_channel: FOI not supported after v4.1.5.9\n"); 
00472         return NULL;
00473 #endif
00474     }
00475     else 
00476     {
00477         pdv_p->foi_unit = channel;
00478     }
00479 
00480     /*
00481      * alloc and get the PCI DV dependent methods struct, which should have
00482      * been initialized in the driver by initcam.
00483      */
00484     if (sizeof(Dependent) > EDT_DEPSIZE)
00485     {
00486         edt_msg(PDVWARN, "pdv_open_channel: sizeof Dependent %d > DEPSIZE %d\n",
00487                 sizeof(Dependent), EDT_DEPSIZE);
00488     }
00489     if ((dd_p = (Dependent *) malloc(EDT_DEPSIZE)) == NULL)
00490     {
00491         pdv_close(pdv_p);
00492         return NULL;
00493     }
00494     pdv_p->dd_p = dd_p;
00495 
00496     if (edt_get_dependent(pdv_p, dd_p) < 0)
00497     {
00498         free(dd_p);
00499         dd_p = 0;
00500         pdv_p->dd_p = NULL;
00501         pdv_close(pdv_p);
00502         return NULL;
00503     }
00504 
00505     if (pdv_p->devid == PDVFOI_ID)
00506     {
00507         pdv_p->foi_unit = edt_get_foiunit(pdv_p);
00508     }
00509 
00510     pdv_p->tmpbufsize = 0;
00511 
00512     pdv_p->dd_p->xilinx_rev = 2;
00513     
00514         if (pdv_p->dd_p->swinterlace ||
00515                 pdv_p->dd_p->interlace_module[0])
00516                 pdv_setup_postproc(pdv_p, pdv_p->dd_p, NULL);
00517 
00518     return pdv_p;
00519 
00520 }
00521 
00522 
00523 
00550 PdvDev *
00551 pdv_open(char *dev_name, int unit)
00552 {
00553     return pdv_open_channel(dev_name, unit, 0);
00554 }
00555 
00556 
00563 void
00564 pdv_setup_dma(PdvDev * pdv_p)
00565 
00566 {
00567     /* This looks like bad stuff to put in the open function... */
00568     /* Since we might not always want to affect */
00569 
00570     edt_set_continuous(pdv_p, 0);
00571     pdv_p->dd_p->started_continuous = 0;
00572 
00573     edt_startdma_reg(pdv_p, PDV_CMD, PDV_ENABLE_GRAB);
00574 }
00575 
00576 
00577 
00586 int
00587 pdv_close(PdvDev * pdv_p)
00588 {
00589     edt_msg(DBG2, "pdv_close()\n");
00590 
00591     if (!pdv_p)
00592         return -1;
00593     if (pdv_p->dd_p)
00594     {
00595         free(pdv_p->dd_p);
00596         pdv_p->dd_p = 0;
00597     }
00598 
00599     return edt_close(pdv_p);
00600 }
00601 
00611 int
00612 pdv_bytes_per_line(int width, int depth)
00613 
00614 {
00615         if (depth == 1)
00616                 return width >> 3;
00617         else if (depth == 2)
00618                 return width >> 2;
00619         else if (depth == 4)
00620                 return width >> 1;
00621         else
00622                 return width * bits2bytes(depth);
00623 }
00624 
00631 int
00632 pdv_get_bytes_per_image(PdvDev *pdv_p)
00633 
00634 {
00635         return pdv_p->dd_p->height * 
00636                         pdv_bytes_per_line(pdv_p->dd_p->width, pdv_p->dd_p->depth);
00637 }
00638 
00639 
00654 int
00655 pdv_get_width(PdvDev * pdv_p)
00656 {
00657     if (!pdv_p->dd_p)
00658         return (0);
00659 
00660     edt_msg(DBG2, "pdv_get_width() %d\n", pdv_p->dd_p->width);
00661 
00662 
00663     return pdv_p->dd_p->width;
00664 }
00665 
00674 int
00675 pdv_get_pitch(PdvDev * pdv_p)
00676 {
00677         int pitch;
00678 
00679     if (!pdv_p->dd_p)
00680         return (0);
00681 
00682         pitch = pdv_bytes_per_line(pdv_p->dd_p->width, 
00683                 pdv_p->dd_p->depth);
00684 
00685     edt_msg(DBG2, "pdv_get_pitch() %d\n", pitch);
00686 
00687 
00688     return pitch ;
00689 }
00690 
00711 int
00712 pdv_get_cam_width(PdvDev * pdv_p)
00713 {
00714     edt_msg(DBG2, "pdv_get_cam_width() %d\n", pdv_p->dd_p->cam_width);
00715 
00716     return pdv_p->dd_p->cam_width;
00717 }
00718 
00730 pdv_get_dmasize(PdvDev * pdv_p)
00731 
00732 {
00733 
00734     Dependent *dd_p = PDV_DEPENDENT(pdv_p);
00735 
00736     int     size;
00737 
00738 
00739     if (dd_p->swinterlace == PDV_INV_RT_INTLV_24_12)
00740                 size = dd_p->width * dd_p->height * 3 / 2;
00741         else if (dd_p->depth > dd_p->extdepth) /* 24 bit bayer filter  or 1 bit data*/
00742                 size = dd_p->height * 
00743                         pdv_bytes_per_line(pdv_p->dd_p->width, pdv_p->dd_p->extdepth);
00744         else
00745                 size = dd_p->height * 
00746                         pdv_bytes_per_line(pdv_p->dd_p->width, pdv_p->dd_p->depth);
00747 
00748 
00749     return size;
00750 }
00751 
00768 int
00769 pdv_setsize(PdvDev * pdv_p, int width, int height)
00770 {
00771    Dependent *dd_p = pdv_p->dd_p;
00772 
00773     edt_msg(DBG2, "pdv_setsize(%d, %d)\n", width, height);
00774 
00775     dd_p->width = width;
00776     dd_p->height = height;
00777 
00778     return pdv_update_size(pdv_p);
00779 
00780 }
00781 
00801 int
00802 pdv_set_cam_width(PdvDev * pdv_p, int value)
00803 {
00804     int     ret;
00805     Dependent *dd_p = pdv_p->dd_p;
00806 
00807     edt_msg(DBG2, "pdv_set_cam_width(%d)\n", value);
00808 
00809     dd_p->cam_width = value;
00810 
00811     ret = edt_set_dependent(pdv_p, dd_p);
00812 
00813     return ret;
00814 }
00815 
00826 int
00827 pdv_get_imagesize(PdvDev * pdv_p)
00828 {
00829 
00830     edt_msg(DBG2, "pdv_get_imagesize() %d\n", pdv_p->dd_p->imagesize);
00831 
00832     return pdv_p->dd_p->imagesize;
00833 }
00834 
00843 int
00844 pdv_get_allocated_size(PdvDev * pdv_p)
00845 {
00846     Dependent *dd_p = pdv_p->dd_p;
00847     int     total = 0;
00848 
00849     int     width = dd_p->width;
00850     int     height = dd_p->height;
00851 
00852 
00853     dd_p->imagesize = dd_p->width * dd_p->height * bits2bytes(dd_p->depth);
00854 
00855     total = pdv_p->dd_p->imagesize + pdv_p->dd_p->slop;
00856 
00857     if (pdv_p->dd_p->header_size && 
00858                 (pdv_p->dd_p->header_position != PDV_HEADER_WITHIN))
00859                 total += pdv_p->dd_p->header_size;
00860 
00861 #ifdef _NT_
00862 
00863     if (total % PAGESIZE)
00864     {
00865         total = ((total / PAGESIZE) + 1) * PAGESIZE;
00866     }
00867 #endif
00868 
00869     edt_msg(DBG2, "pdv_get_allocated_size() %d\n", total);
00870 
00871     return total;
00872 
00873 }
00874 
00894 int
00895 pdv_set_timeout(PdvDev * pdv_p, int value)
00896 {
00897     Dependent *dd_p = pdv_p->dd_p;
00898 
00899     if (value < 0)
00900     {
00901         edt_msg(DBG2, "pdv_set_timeout(%d) (< 0, going back to auto)\n", value);
00902 
00903         pdv_p->dd_p->user_timeout_set = 0;
00904         edt_set_dependent(pdv_p, dd_p);
00905         return pdv_auto_set_timeout(pdv_p);
00906     }
00907     else
00908     {
00909         edt_msg(DBG2, "pdv_set_timeout(%d) (user set, overriding auto)\n", value);
00910 
00911         pdv_p->dd_p->user_timeout_set = 1;
00912         pdv_p->dd_p->user_timeout = value;
00913         edt_set_dependent(pdv_p, dd_p);
00914         return edt_set_rtimeout(pdv_p, value);
00915     }
00916 }
00917 
00932 int
00933 pdv_get_timeout(PdvDev * pdv_p)
00934 {
00935 
00936     edt_msg(DBG2, "pdv_get_timeout()\n");
00937 
00938     return edt_get_rtimeout(pdv_p);
00939 }
00940 
00953 int
00954 pdv_picture_timeout(PdvDev * pdv_p, int value)
00955 {
00956     return pdv_set_timeout(pdv_p, value);
00957 }
00958  /* end settings */
00960 
00961 
01000 int
01001 pdv_timeouts(PdvDev * pdv_p)
01002 {
01003     int     ret;
01004 
01005     ret = edt_timeouts(pdv_p);
01006     edt_msg(DBG2, "pdv_timeouts(%d)\n", ret);
01007     return ret;
01008 }
01009 
01010 
01023 int
01024 pdv_timeout_cleanup(PdvDev * pdv_p)
01025 {
01026     int     curdone, curtodo;
01027 
01028     curdone = edt_done_count(pdv_p);
01029     curtodo = edt_get_todo(pdv_p);
01030     pdv_stop_continuous(pdv_p);
01031     edt_msleep(500);
01032     edt_set_buffer(pdv_p, curdone);
01033     edt_reg_write(pdv_p, PDV_CMD, PDV_RESET_INTFC);
01034     pdv_setup_continuous(pdv_p);
01035     return curtodo - curdone;
01036 }
01037  /* end acquisition */
01039 
01040 
01058 int
01059 pdv_get_height(PdvDev * pdv_p)
01060 {
01061     if (!pdv_p->dd_p)
01062         return (0);
01063 
01064     edt_msg(DBG2, "pdv_get_height() %d\n", pdv_p->dd_p->height);
01065 
01066     return pdv_p->dd_p->height;
01067 }
01068 
01088 int
01089 pdv_get_cam_height(PdvDev * pdv_p)
01090 {
01091 
01092     edt_msg(DBG2, "pdv_get_cam_height() %d\n", pdv_p->dd_p->cam_height);
01093 
01094     return pdv_p->dd_p->cam_height;
01095 }
01096 
01097 
01114 int
01115 pdv_get_frame_height(PdvDev * pdv_p)
01116 {
01117 
01118     edt_msg(DBG2, "pdv_get_cam_height() %d\n", pdv_p->dd_p->cam_height);
01119 
01120     return pdv_p->dd_p->frame_height;
01121 }
01122  /* end settings */
01124 
01134 int
01135 pdv_update_size(PdvDev *pdv_p)
01136 
01137 {
01138         Dependent *dd_p = pdv_p->dd_p;
01139         int ret;
01140 
01141     edt_msg(DBG2, "update_size\n");
01142 
01143     dd_p->imagesize = dd_p->height * pdv_get_pitch(pdv_p);
01144 
01145     ret = edt_set_dependent(pdv_p, dd_p);
01146 
01147     if (pdv_p->ring_buffer_numbufs > 0)
01148                 pdv_multibuf(pdv_p, pdv_p->ring_buffer_numbufs);
01149 
01150     if (dd_p->swinterlace)
01151     {
01152                 pdv_alloc_tmpbuf(pdv_p);
01153     }
01154 
01155         return ret;
01156 }
01157 
01169 int
01170 pdv_set_width(PdvDev * pdv_p, int value)
01171 {
01172     Dependent *dd_p = pdv_p->dd_p;
01173 
01174     edt_msg(DBG2, "pdv_set_width(%d)\n", value);
01175 
01176     dd_p->width = value;
01177 
01178         return pdv_update_size(pdv_p);
01179 
01180 }
01181 
01190 int
01191 pdv_set_height(PdvDev * pdv_p, int value)
01192 {
01193     Dependent *dd_p = pdv_p->dd_p;
01194 
01195     edt_msg(DBG2, "pdv_set_height(%d)\n", value);
01196 
01197     dd_p->height = value;
01198 
01199         return pdv_update_size(pdv_p);
01200 
01201 }
01202 
01220 int
01221 pdv_set_cam_height(PdvDev * pdv_p, int value)
01222 {
01223     int     ret;
01224     Dependent *dd_p = pdv_p->dd_p;
01225 
01226     edt_msg(DBG2, "pdv_set_cam_height(%d)\n", value);
01227 
01228     dd_p->cam_height = value;
01229 
01230     ret = edt_set_dependent(pdv_p, dd_p);
01231     return ret;
01232 }
01233 
01234 
01243 int
01244 pdv_get_depth(PdvDev * pdv_p)
01245 {
01246     if (!pdv_p->dd_p)
01247         return (0);
01248 
01249     edt_msg(DBG2, "pdv_get_depth() %d\n", pdv_p->dd_p->depth);
01250 
01251     return pdv_p->dd_p->depth;
01252 }
01253 
01271 int
01272 pdv_get_extdepth(PdvDev * pdv_p)
01273 {
01274 
01275     edt_msg(DBG2, "pdv_get_extdepth() %d\n", pdv_p->dd_p->extdepth);
01276 
01277     return pdv_p->dd_p->extdepth;
01278 }
01279 
01307 int
01308 pdv_set_depth(PdvDev * pdv_p, int value)
01309 {
01310     Dependent *dd_p = pdv_p->dd_p;
01311 
01312     dd_p->depth = value;
01313 
01314     /* set cameralink data path register, if appropriate -- note that
01315      * odball values are generally  handled differently (e.g.
01316      * pdvcamlk_pir which has hard-coded depth)
01317      */
01318     if (pdv_is_cameralink(pdv_p))
01319     {
01320         int reg;
01321 
01322         if ((value >= 8) && (value <= 16))
01323             reg = value-1;
01324         else if (value == 24 || value == 32)
01325             reg = 0x7;
01326         else if (value == 30)
01327             reg = 0x9;
01328         else reg = 0;
01329 
01330         if (reg)
01331         {
01332             if (dd_p->dual_channel)
01333                 reg |= 0x10;
01334             dd_p->dual_channel = reg;
01335             edt_reg_write(pdv_p, PDV_CL_DATA_PATH, dd_p->cl_data_path);
01336         }
01337     }
01338 
01339     return pdv_update_size(pdv_p);
01340 
01341 }
01342 
01369 int
01370 pdv_set_extdepth(PdvDev * pdv_p, int value)
01371 {
01372     int     ret;
01373     Dependent *dd_p = pdv_p->dd_p;
01374 
01375     dd_p->extdepth = value;
01376 
01377     edt_msg(DBG2, "pdv_set_extdepth(%d)\n", value);
01378 
01379     ret = edt_set_dependent(pdv_p, dd_p);
01380 
01381     return ret;
01382 }
01383 
01395 int
01396 pdv_set_cameratype(PdvDev * pdv_p, char *model)
01397 {
01398     Dependent *dd_p = pdv_p->dd_p;
01399 
01400     edt_msg(DBG2, "pdv_set_cameratype(%s)\n", model);
01401 
01402     strcpy(dd_p->cameratype, model);
01403 
01404     return edt_set_dependent(pdv_p, dd_p);
01405 }
01406 
01407 
01424 char   *
01425 pdv_get_cameratype(PdvDev * pdv_p)
01426 {
01427     edt_msg(DBG2, "pdv_get_cameratype()\n");
01428 
01429     return pdv_p->dd_p->cameratype;
01430 }
01431 
01432 
01449 char   *
01450 pdv_get_camera_class(PdvDev * pdv_p)
01451 {
01452     edt_msg(DBG2, "pdv_get_camera_class()\n");
01453 
01454     return pdv_p->dd_p->camera_class;
01455 }
01456 
01457 
01467 char   *
01468 pdv_get_camera_model(PdvDev * pdv_p)
01469 {
01470     edt_msg(DBG2, "pdv_get_camera_model()\n");
01471 
01472     return pdv_p->dd_p->camera_model;
01473 }
01474 
01485 char   *
01486 pdv_get_camera_info(PdvDev * pdv_p)
01487 {
01488     edt_msg(DBG2, "pdv_get_camera_info()\n");
01489 
01490     return pdv_p->dd_p->camera_info;
01491 }
01492 
01504 char   *
01505 pdv_camera_type(PdvDev * pdv_p)
01506 {
01507     edt_msg(DBG2, "pdv_camera_type()\n");
01508 
01509     return pdv_p->dd_p->cameratype;
01510 }
01511  /* end settings */
01513 
01514 static int
01515 smd_read_reg(PdvDev * pdv_p, int reg)
01516 {
01517     u_char  buf[128];
01518     int     ret;
01519 
01520     /* flush out any junk */
01521     pdv_serial_read(pdv_p, (char *) buf, 64);
01522 
01523     /* read SMD frame rate register */
01524     buf[0] = (u_char) reg;
01525     pdv_serial_binary_command(pdv_p, (char *) buf, 1);
01526 
01527     ret = pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, pdv_p->dd_p->serial_respcnt);
01528     if (ret == 0)
01529         return -1;
01530     pdv_serial_read(pdv_p, (char *) buf, ret);
01531     return (int) buf[0];
01532 }
01533 
01557 int
01558 pdv_set_exposure(PdvDev * pdv_p, int value)
01559 {
01560     int     ret = -1;
01561     Dependent *dd_p = pdv_p->dd_p;
01562     char    cmdstr[64];
01563     int     n;
01564 
01565     edt_msg(DBG2, "pdv_set_exposure(%d)\n", value);
01566 
01567     dd_p->shutter_speed = value;
01568 
01569     if (edt_set_dependent(pdv_p, dd_p) < 0)
01570     {
01571         edt_msg(DBG2, "pdv_set_exposure ret %d\n", ret);
01572         return -1;
01573     }
01574 
01575     pdv_auto_set_timeout(pdv_p);
01576 
01577     if ((dd_p->camera_shutter_timing == AIA_MCL)
01578           && (dd_p->mode_cntl_norm & 0xf0)
01579           && (!dd_p->trig_pulse))
01580     {
01581         ret = pdv_set_exposure_mcl(pdv_p, value);
01582     }
01583     else if (dd_p->camera_shutter_timing == AIA_MCL_100US)
01584     {
01585         /* in this case do mcl even if trig_pulse */
01586         ret = pdv_set_exposure_mcl(pdv_p, value);
01587     }
01588     else if ((strlen(dd_p->serial_exposure) > 0)
01589         && (dd_p->serial_format == SERIAL_BINARY))
01590     {
01591         send_serial_binary_cmd(pdv_p, dd_p->serial_exposure, value);
01592     }
01593     else if ((strlen(dd_p->serial_exposure) > 0)
01594              && ((dd_p->serial_format == SERIAL_ASCII)
01595                  || (dd_p->serial_format == SERIAL_ASCII_HEX)
01596                  || (dd_p->serial_format == SERIAL_PULNIX_1010)))
01597     {
01598         /* special serial cmd for ham 4880 */
01599         /* ALERT: get rid of this, s/b camera_shutter_timing here and */
01600         /* in config files and everywhere else....! */
01601         if (dd_p->camera_shutter_timing == HAM_4880_SER)
01602         {
01603             int     minutes;
01604             int     seconds;
01605             int     useconds;
01606 
01607             minutes = value / 60000;
01608             value -= minutes * 60000;
01609 
01610             seconds = value / 1000;
01611             value -= seconds * 1000;
01612 
01613             useconds = value;
01614 
01615             sprintf(cmdstr, "%s %04d:%02d.%03d",
01616                     dd_p->serial_exposure, minutes, seconds, useconds);
01617         }
01618         else
01619         {
01620             if (dd_p->serial_format == SERIAL_ASCII_HEX)
01621                 sprintf(cmdstr, "%s %02x", dd_p->serial_exposure, value);
01622 
01623             else if (dd_p->serial_format == SERIAL_PULNIX_1010)
01624                 sprintf(cmdstr, "%s%d", dd_p->serial_exposure, value);
01625 
01626             else if (dd_p->serial_exposure[0] == ':')   /* pulnix 1300 fmt */
01627             {
01628                 /*
01629                  * sprintf(cmdstr, "%s%c", dd_p->serial_exposure, '0' +
01630                  * value);
01631                  */
01632                 sprintf(cmdstr, "%s%x", dd_p->serial_exposure, value);
01633                 dd_p->serial_respcnt = 3;
01634             }
01635             else if (dd_p->serial_exposure[1] == '=')   /* thomson camelia fmt */
01636             {
01637                 sprintf(cmdstr, "%s%d", dd_p->serial_exposure, value);
01638             }
01639             else                /* kodak format */
01640             {
01641                 sprintf(cmdstr, "%s %d", dd_p->serial_exposure, value);
01642             }
01643         }
01644 
01645         ret = pdv_serial_command_flagged(pdv_p, cmdstr, SCFLAG_NORESP);
01646         if (pdv_p->devid == PDVFOI_ID)
01647             n = pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, 0);
01648         else
01649             n = pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, pdv_p->dd_p->serial_respcnt);
01650         if (*pdv_p->dd_p->serial_response)
01651             if (n)
01652                 pdv_serial_read(pdv_p, cmdstr, n);
01653 
01654     }
01655     else if ((dd_p->camera_shutter_timing == SPECINST_SERIAL)
01656              || (dd_p->camera_shutter_speed == SPECINST_SERIAL))
01657     {
01658         ret = pdv_set_exposure_specinst(pdv_p, value);
01659     }
01660     else if (dd_p->camera_shutter_timing == SMD_SERIAL)
01661     {
01662         ret = pdv_set_exposure_smd(pdv_p, value);
01663     }
01664     else if (dd_p->camera_shutter_timing == PTM6710_SERIAL)
01665     {
01666         ret = pdv_set_exposure_ptm6710_1020(pdv_p, value);
01667     }
01668     else if (dd_p->camera_shutter_timing == PTM1020_SERIAL)
01669     {
01670         ret = pdv_set_exposure_ptm6710_1020(pdv_p, value);
01671     }
01672     else if (dd_p->camera_shutter_timing == TIMC1001_SERIAL)
01673     {
01674         ret = pdv_set_exposure_timc1001pf(pdv_p, value);
01675     }
01676     else if (dd_p->camera_shutter_timing == ADIMEC_SERIAL)
01677     {
01678         ret = pdv_set_exposure_adimec(pdv_p, value);
01679     }
01680     else if (dd_p->camera_shutter_timing == BASLER202K_SERIAL)
01681     {
01682         ret = pdv_set_exposure_basler202k(pdv_p, value);
01683     }
01684     else if (dd_p->camera_shutter_timing == SU320_SERIAL)
01685     {
01686         ret = pdv_set_exposure_su320(pdv_p, value);
01687     }
01688     else if (dd_p->camera_shutter_timing == HAM_4880_SER)
01689     {
01690         /* controlled by serial; do nothing */
01691     }
01692     else if (dd_p->camera_shutter_timing == AIA_SERIAL)
01693     {
01694         /* controlled by serial; do nothing */
01695     }
01696     else if (dd_p->camera_shutter_timing == AIA_SERIAL_ES40)
01697     {
01698         /* controlled by serial; do nothing */
01699     }
01700     else if (dd_p->camera_shutter_timing == AIA_TRIG)
01701     {
01702         ret = pdv_set_exposure_mcl(pdv_p, value);
01703     }
01704     else if (!dd_p->trig_pulse)
01705     {
01706         /* default to aia mcl if not trig_pulse */
01707         ret = pdv_set_exposure_mcl(pdv_p, value);
01708     }
01709 
01710     edt_msg(DBG2, "pdv_set_exposure returns %d\n", ret);
01711     return (ret);
01712 }
01713 
01730 int
01731 pdv_set_exposure_mcl(PdvDev * pdv_p, int value)
01732 {
01733     u_int   data_path;
01734 
01735     if (value < 0)
01736         value = 0;
01737     if (value > 25500)
01738         value = 25500;
01739 
01740     pdv_p->dd_p->shutter_speed = value;
01741 
01742     data_path = pdv_p->dd_p->datapath_reg;
01743     data_path &= ~PDV_MULTIPLIER_MASK;
01744 
01745 
01746     /*
01747      * special case microsecond shutter timer
01748      */
01749     if (pdv_p->dd_p->camera_shutter_timing == AIA_MCL_100US)
01750     {
01751         edt_msg(DBG2, "pdv_set_exposure_mcl(%d) (100US)\n", value);
01752 
01753         if (value < 256)
01754         {
01755             data_path |= PDV_MULTIPLIER_100US;
01756         }
01757         else if (value < 2560)
01758         {
01759             /* already turned off multiplier */
01760             value = (value + 5) / 10;
01761         }
01762         else if (value < 25600)
01763         {
01764             data_path |= PDV_MULTIPLIER_10MS;
01765             value = (value + 50) / 100;
01766         }
01767         else if (value < 256000)
01768         {
01769             data_path |= PDV_MULTIPLIER_100MS;
01770             value = (value + 50) / 1000;
01771         }
01772     }
01773     else
01774     {
01775         edt_msg(DBG2, "pdv_set_exposure_mcl(%d)\n", value);
01776 
01777         if (value < 256)
01778         {
01779             /* already turned off multiplier */
01780         }
01781         else if (value < 2560)
01782         {
01783             data_path |= PDV_MULTIPLIER_10MS;
01784             value = (value + 5) / 10;
01785         }
01786         else
01787         {
01788             data_path |= PDV_MULTIPLIER_100MS;
01789             value = (value + 50) / 100;
01790         }
01791     }
01792 
01793     pdv_p->dd_p->datapath_reg = data_path;
01794     edt_reg_write(pdv_p, PDV_SHUTTER, value);
01795     edt_reg_write(pdv_p, PDV_DATA_PATH, data_path);
01796 
01797     return 0;
01798 }
01799 
01803 pdv_set_exposure_smd(PdvDev * pdv_p, int value)
01804 {
01805     int     fp = 0;
01806     u_char  buf[128];
01807     int     n;
01808     int     ret = 0;
01809     int     smd_reg1, smd_reg3;
01810 
01811 
01812     if (Smd_type == NOT_SET)
01813     {
01814         Smd_type = smd_read_reg(pdv_p, SMD_READ_CAMTYPE);
01815         if ((Smd_type & 0xfff) == 0xfff)        /* sometimes there's garbage
01816                                                  * at first; if so try again */
01817             Smd_type = smd_read_reg(pdv_p, SMD_READ_CAMTYPE);
01818     }
01819 
01820     /* send SMD write integration reg. command and arg */
01821     switch (Smd_type)
01822     {
01823     case SMD_TYPE_4M4:
01824         /*
01825          * set time to send, then write that based on msecs (value is int so
01826          * can't do 0.5msec, just use 0 for that -- $#^&*@ screwy way to do
01827          * it if you ask me.....) buf[0] = (u_char) SMD_4M4_WRITE_R2;
01828          */
01829         if (value == 0)         /* 500us */
01830             buf[1] = 0x7d;
01831         else if (value == 1)    /* 1ms */
01832             buf[1] = 0x7b;
01833         else if (value == 2)    /* 2ms */
01834             buf[1] = 0x77;
01835         else if (value <= 4)    /* 4ms */
01836             buf[1] = 0x6f;
01837         else if (value <= 8)    /* 8ms */
01838             buf[1] = 0x5f;
01839         else if (value <= 16)   /* 16ms */
01840             buf[1] = 0x3f;
01841         else                    /* 32ms (default) */
01842             buf[1] = 0x00;
01843         /*
01844          * send write r2 (integration reg) command
01845          */
01846         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
01847         break;
01848 
01849     case SMD_TYPE_BT25:
01850         /*
01851          * adjust timeout multiplier according to frame rate
01852          */
01853         buf[0] = (u_char) SMD_BT25_WRITE_R2;
01854         if (Smd_rate == NOT_SET)
01855         {
01856             if ((Smd_rate = smd_read_reg(pdv_p, SMD_BT25_READ_FRAMERATE)) == -1)
01857                 edt_msg(PDVWARN, "libpdv: no response from SMD camera rate reg read\n");
01858             if (pdv_p->dd_p->timeout_multiplier < Smd_rate)
01859             {
01860                 pdv_p->dd_p->timeout_multiplier = Smd_rate;
01861                 pdv_auto_set_timeout(pdv_p);
01862             }
01863         }
01864         buf[1] = (u_char) value;
01865         /*
01866          * send write r2 (integration reg) command
01867          */
01868         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
01869 
01870         /* SMD doesn't resp but do a dummy wait to make sure its done */
01871         pdv_serial_wait(pdv_p, 100, 64);
01872         break;
01873 
01874     case SMD_TYPE_1M30P:
01875     case SMD_TYPE_6M3P:
01876         buf[0] = (u_char) SMD_1M30P_REG_W_INTEG0;
01877         buf[1] = value & 0xff;
01878         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
01879 
01880         buf[0] = (u_char) SMD_1M30P_REG_W_INTEG1;
01881         buf[1] = (value & 0xff00) >> 8;
01882         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
01883 
01884         buf[0] = (u_char) SMD_1M30P_REG_W_INTEG2;
01885         buf[1] = (value & 0xff0000) >> 16;
01886         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
01887 
01888         /*
01889          * SMD 1M30p  shutter speeds are in uSecs, so fake out
01890          * pdv_auto_set_timeout, then switch speed back to actual value
01891          */
01892         /*
01893          * ALERT: should take frame rate (& binning?) into account here too
01894          */
01895         pdv_p->dd_p->shutter_speed = value / 1000;
01896         pdv_auto_set_timeout(pdv_p);
01897         pdv_p->dd_p->shutter_speed = value;
01898         break;
01899 
01900     case SMD_TYPE_1M15P:
01901         if ((smd_reg1 = smd_read_reg(pdv_p, SMD_1M15P_READ_R1)) == -1)
01902         {
01903             edt_msg(PDVWARN, "libpdv: no response from SMD R1 reg read\n");
01904             return -1;
01905         }
01906 
01907 
01908         buf[0] = (u_char) SMD_1M15P_WRITE_R1;
01909 
01910         /*
01911          * valid values for this camera are 0, 1, 2, 4 and 8, but allow values
01912          * in between and just round down 
01913          */
01914         if (value == 0)
01915         {
01916             buf[1] = (smd_reg1 &~ SMD_1M15P_R1_INTMSK) | 0x0; /* NONE */
01917             fp = 65000;
01918         }
01919         else if (value == 1)
01920         {
01921             buf[1] = (smd_reg1 &~ SMD_1M15P_R1_INTMSK) | 0x7; /* 1 ms */
01922             fp = 65000;
01923         }
01924         else if (value < 4)
01925         {
01926             buf[1] = (smd_reg1 &~ SMD_1M15P_R1_INTMSK) | 0x6; /* 2 ms */
01927             fp = 64000;
01928         }
01929         else if (value < 7)
01930         {
01931             buf[1] = (smd_reg1 &~ SMD_1M15P_R1_INTMSK) | 0x5; /* 4 ms */
01932             fp = 62000;
01933         }
01934         else if (value == 8)
01935         {
01936             buf[1] = (smd_reg1 &~ SMD_1M15P_R1_INTMSK) | 0x4; /* 8 ms */
01937             fp = 58000;
01938         }
01939         else return -1;
01940 
01941         if (smd_reg1 & SMD_1M15P_R1_TRIGMODE)
01942         {
01943             /* if binned and triggered, use half the frame delay */ 
01944             smd_reg3 = smd_read_reg(pdv_p, SMD_1M15P_READ_R3);
01945             if (smd_reg3 & 0x40) /* 2x2 bin mode bit */
01946                 fp /= 2;
01947             pdv_set_frame_period(pdv_p, fp, PDV_FVAL_ADJUST);
01948         }
01949 
01950         pdv_p->dd_p->shutter_speed = value;
01951         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
01952         break;
01953 
01954     default:
01955         ret = -1;
01956         edt_msg(PDVWARN, "libpdv: unknown SMD camera type %02x\n", Smd_type);
01957         break;
01958     }
01959 
01960     if (!ret)
01961     {
01962         /* SMD doesn't respond but do a dummy wait to make sure its done */
01963         n = pdv_serial_wait(pdv_p, 100, 64);
01964         if (n > 127)
01965             n = 127;
01966         if (n)
01967             pdv_serial_read(pdv_p, (char *) buf, n);
01968     }
01969     return ret;
01970 }
01971 
01980 static int
01981 pdv_set_exposure_timc1001pf(PdvDev * pdv_p, int value)
01982 {
01983     Dependent *dd_p = pdv_p->dd_p;
01984     u_int   mcl = edt_reg_read(pdv_p, PDV_MODE_CNTL) & 0xf1;
01985 
01986     if ((value >= 0) && (value <= 7))
01987     {
01988         dd_p->shutter_speed = value;
01989         mcl |= (value << 1);
01990         edt_reg_write(pdv_p, PDV_MODE_CNTL, mcl);
01991         return 0;
01992     }
01993     return -1;
01994 }
01995 
01999 pdv_set_exposure_ptm6710_1020(PdvDev * pdv_p, int value)
02000 {
02001     char    buf[128];
02002     int     ret = 0;
02003 
02004     if ((value < 0) || (value > 9))
02005         return -1;
02006 
02007     sprintf(buf, ":SM%d", value);
02008     pdv_serial_command_flagged(pdv_p, buf, SCFLAG_NORESP);
02009 
02010     return 0;
02011 }
02012 
02016 pdv_set_gain_ptm6710_1020(PdvDev * pdv_p, int value)
02017 {
02018     char    buf[128];
02019     int     ret = 0;
02020 
02021     if ((value < 0) || (value > 0xff))
02022         return -1;
02023 
02024     sprintf(buf, ":GM%02X", value);
02025     pdv_serial_command_flagged(pdv_p, buf, SCFLAG_NORESP);
02026 
02027     return 0;
02028 }
02029 
02034 pdv_set_gain_hc8484(PdvDev * pdv_p, int value)
02035 {
02036     char    buf[128];
02037     int     ret = 0;
02038 
02039     if ((value != 0) && (value != 1))
02040         return -1;
02041     sprintf(buf, "CEG %c", value ? 'H' : 'L');
02042     pdv_serial_command_flagged(pdv_p, buf, SCFLAG_NORESP);
02043 
02044     return 0;
02045 }
02046 
02051 static int
02052 pdv_set_exposure_adimec(PdvDev * pdv_p, int value)
02053 {
02054     Dependent *dd_p = pdv_p->dd_p;
02055     char    cmdbuf[32];
02056 
02057 
02058     sprintf(cmdbuf, "@IT%d", value);
02059     pdv_serial_command(pdv_p, cmdbuf);
02060     return 0;
02061 }
02062 
02063 static int
02064 pdv_set_gain_adimec(PdvDev * pdv_p, int value)
02065 {
02066     Dependent *dd_p = pdv_p->dd_p;
02067     char    cmdbuf[32];
02068 
02069 
02070     sprintf(cmdbuf, "@GA%d", value);
02071     pdv_serial_command(pdv_p, cmdbuf);
02072     return 0;
02073 }
02074 
02075 static int
02076 pdv_set_blacklevel_adimec(PdvDev * pdv_p, int value)
02077 {
02078     Dependent *dd_p = pdv_p->dd_p;
02079     char    cmdbuf[32];
02080 
02081 
02082     sprintf(cmdbuf, "@BL%d;%d", value, value);
02083     pdv_serial_command(pdv_p, cmdbuf);
02084     return 0;
02085 }
02086 
02087 
02092 static int
02093 pdv_set_exposure_specinst(PdvDev * pdv_p, int value)
02094 {
02095     edt_msg(DBG2, "pdv_set_exposure_specinst(%d)\n", value);
02096 
02097     if (pdv_specinst_setparam(pdv_p, 'G', 8, value) != 0)
02098     {
02099         edt_msg(DBG2, "pdv_set_exposure_specinst() apparently FAILED\n");
02100         return -1;
02101     }
02102     return 0;
02103 }
02104 
02109 static int
02110 pdv_set_gain_specinst(PdvDev * pdv_p, int value)
02111 {
02112     edt_msg(DBG2, "pdv_set_gain_specinst(%d)\n", value);
02113 
02114     if (pdv_specinst_setparam(pdv_p, 'G', 11, value) != 0)
02115     {
02116         edt_msg(DBG2, "pdv_set_gain_specinst() apparently FAILED\n");
02117         return -1;
02118     }
02119     return 0;
02120 }
02121 
02127 static int
02128 pdv_set_exposure_su320(PdvDev * pdv_p, int value)
02129 {
02130     Dependent *dd_p = pdv_p->dd_p;
02131     char    cmdbuf[32];
02132     char resp[1024];
02133     int n;
02134 
02135     sprintf(cmdbuf, "INT%d", value);
02136     pdv_serial_command(pdv_p, cmdbuf);
02137     pdv_serial_wait(pdv_p, 100, 20);
02138     if ((n = pdv_serial_read(pdv_p, resp, 20)) != 20)
02139         return -1;
02140     return 0;
02141 }
02142 
02143 
02144 static int
02145 pdv_specinst_setparam(PdvDev * pdv_p, char cmd, u_long offset, u_long value)
02146 {
02147     int     ret1, ret2, ret3;
02148     char    resp1[32];
02149     char    resp2[32];
02150     char    buf[32];
02151     u_char  cmdbuf[5];
02152     u_char  offsetbuf[5];
02153     u_char  parambuf[5];
02154     int     si_wait = 200;
02155 
02156     edt_msg(DBG2, "pdv_specinst_setparam(%c %04x %04x)\n", cmd, offset, value);
02157 
02158     dvu_long_to_charbuf(offset, offsetbuf);
02159     dvu_long_to_charbuf(value, parambuf);
02160 
02161     cmdbuf[0] = cmd;
02162 
02163     pdv_serial_binary_command(pdv_p, (char *) cmdbuf, 1);
02164     pdv_serial_wait_next(pdv_p, si_wait, 31);
02165     ret1 = pdv_serial_read(pdv_p, resp1, 31);
02166 
02167     pdv_serial_binary_command(pdv_p, (char *) offsetbuf, 4);
02168     pdv_serial_wait_next(pdv_p, si_wait, 31);
02169     ret2 = pdv_serial_read(pdv_p, buf, 31);
02170 
02171     pdv_serial_binary_command(pdv_p, (char *) parambuf, 4);
02172     pdv_serial_wait_next(pdv_p, si_wait, 31);
02173     ret3 = pdv_serial_read(pdv_p, resp2, 31);
02174 
02175     if ((ret1 != 1) || (ret3 != 1) || (resp1[0] != 'G') || (resp2[0] != 'Y'))
02176     {
02177         edt_msg(DBG1, "invalid or missing serial response from specinst\n");
02178         return -1;
02179     }
02180     return 0;
02181 }
02182 
02196 int
02197 pdv_send_basler_command(PdvDev * pdv_p, int cmd, int rwflag, int len, int data)
02198 {
02199     int       i;
02200     u_char    frame[32];
02201     u_char    rwbit = (rwflag & 0x1) << 7;
02202 
02203     frame[0] = cmd;