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;                           
02204     frame[1] = ((u_char)len & 0xef) | rwbit;
02205     for (i=0; i<len; i++)
02206         frame[i+2] = (data >> (8 * i)) & 0xff;
02207 
02208     return pdv_send_basler_frame(pdv_p, frame, len+2);
02209 }
02210 
02216 int
02217 pdv_set_exposure_basler202k(PdvDev * pdv_p, int value)
02218 {
02219     Dependent *dd_p = pdv_p->dd_p;
02220     u_char    rframe[8];
02221 
02222     memset(rframe, 0, 8);
02223     pdv_send_basler_command(pdv_p, 0xa6, 0, 3, value);
02224     pdv_read_basler_frame(pdv_p, rframe, 1);
02225     if (rframe[0] != 0x6) /* ACK */
02226         return -1;
02227     return 0;
02228 }
02229 
02230 int
02231 pdv_set_gain_basler202k(PdvDev * pdv_p, int valuea, int valueb)
02232 {
02233     Dependent *dd_p = pdv_p->dd_p;
02234     u_char    rframe[8];
02235 
02236     memset(rframe, 0, 8);
02237     pdv_send_basler_command(pdv_p, 0x80, 0, 2, valuea);
02238     pdv_read_basler_frame(pdv_p, rframe, 1);
02239     if (rframe[0] != 0x6) /* ACK */
02240         return -1;
02241 
02242     memset(rframe, 0, 8);
02243     pdv_send_basler_command(pdv_p, 0x82, 0, 2, valueb);
02244     pdv_read_basler_frame(pdv_p, rframe, 1);
02245     if (rframe[0] != 0x6) /* ACK */
02246         return -1;
02247 
02248     return 0;
02249 }
02250 
02251 int
02252 pdv_set_offset_basler202k(PdvDev * pdv_p, int valuea, int valueb)
02253 {
02254     Dependent *dd_p = pdv_p->dd_p;
02255     u_char    rframe[8];
02256 
02257     memset(rframe, 0, 8);
02258     pdv_send_basler_command(pdv_p, 0x81, 0, 2, valuea);
02259     pdv_read_basler_frame(pdv_p, rframe, 1);
02260     if (rframe[0] != 0x6) /* ACK */
02261         return -1;
02262 
02263     memset(rframe, 0, 8);
02264     pdv_send_basler_command(pdv_p, 0x83, 0, 2, valueb);
02265     pdv_read_basler_frame(pdv_p, rframe, 1);
02266     if (rframe[0] != 0x6) /* ACK */
02267         return -1;
02268     return 0;
02269 }
02270 
02287 int
02288 pdv_set_exposure_duncan_ch(PdvDev * pdv_p, int value, int ch)
02289 {
02290     Dependent *dd_p = pdv_p->dd_p;
02291         
02292     u_char    msg[8];
02293     u_char    rmsg[16];
02294 
02295     msg[0] = 0x04;                              /* LSB size */
02296     msg[1] = 0x00;                              /* MSB size */
02297     msg[2] = 0x14;                              /* command byte */
02298     msg[3] = (u_char)(ch & 0xff);               /* channel*/
02299     msg[4] = (u_char)(value & 0xff);            /* value lsb */
02300     msg[5] = (u_char)((value >> 8) & 0xff);     /* value msb */
02301     pdv_send_duncan_frame(pdv_p, msg, 6);
02302     pdv_read_duncan_frame(pdv_p, rmsg);
02303     return 0;
02304 }
02305 
02322 int
02323 pdv_set_gain_duncan_ch(PdvDev * pdv_p, int value, int ch)
02324 {
02325     Dependent *dd_p = pdv_p->dd_p;
02326         
02327     u_char    msg[8];
02328     u_char    rmsg[16];
02329 
02330     msg[0] = 0x04;                              /* LSB size */
02331     msg[1] = 0x00;                              /* MSB size */
02332     msg[2] = 0x02;                              /* command byte */
02333     msg[3] = (u_char)(ch & 0xff);               /* channel*/
02334     msg[4] = (u_char)(value & 0xff);            /* value lsb */
02335     msg[5] = (u_char)((value >> 8) & 0xff);     /* value msb */
02336     pdv_send_duncan_frame(pdv_p, msg, 6);
02337     pdv_read_duncan_frame(pdv_p, rmsg);
02338     return 0;
02339 }
02340 
02341 
02346 static void
02347 send_serial_binary_cmd(PdvDev * pdv_p, char *hexstr, int value)
02348 {
02349     int     nb;
02350     u_char  hbuf[2];
02351     char    resp[128];
02352     char    bs[16][3];
02353     int     ret;
02354 
02355     edt_msg(DBG2, "send_serial_binary_cmd(\"%s\", %d)\n", hexstr, value);
02356 
02357     nb = sscanf(hexstr, "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s",
02358                 bs[0], bs[1], bs[2], bs[3], bs[4], bs[5], bs[6], bs[7],
02359               bs[8], bs[9], bs[10], bs[11], bs[12], bs[13], bs[14], bs[15]);
02360 
02361     pdv_serial_binary_command(pdv_p, (char *) hbuf, nb);
02362     pdv_serial_wait(pdv_p, 100, 3);
02363 
02364     if (*pdv_p->dd_p->serial_response)
02365         ret = pdv_serial_read(pdv_p, resp, 50);
02366 
02367     {
02368 
02369         edt_msg(DBG2, "serial response <%s> (%d)\n", hex_to_str(resp, ret), ret);
02370     }
02371 }
02372 
02399 int
02400 pdv_auto_set_timeout(PdvDev * pdv_p)
02401 {
02402     Dependent *dd_p = pdv_p->dd_p;
02403     int     user_timeout = dd_p->user_timeout;
02404     int     user_set = dd_p->user_timeout_set;
02405     int     tmult = dd_p->timeout_multiplier;
02406     int     cur_timeout = edt_get_rtimeout(pdv_p);
02407     int     timeout;
02408     int     exposure;
02409     int     pdiv = 1;
02410     int     ret = 0;
02411     int     xfersize;
02412 
02413     /*
02414      * tmult is for cameras with non-standard integration times
02415      */
02416     if (tmult < 1)
02417         tmult = 1;
02418 
02419     /* pixel clock speed less than 5? Hope not! */
02420     if (dd_p->pclock_speed < 5)
02421         dd_p->pclock_speed = 5;
02422     pdiv = dd_p->pclock_speed / 5;
02423 
02424     if (((exposure = dd_p->shutter_speed)) < 500)
02425         exposure = 500; /* conservative enough? hope so */
02426 
02427     xfersize = dd_p->cam_width * dd_p->cam_height * bits2bytes(dd_p->depth);
02428     timeout = (((xfersize * tmult) / 4000) / pdiv) + exposure;
02429 
02430     edt_msg(DBG2, "pdv_auto_set_timeout(): current %d new %d exposure %d pclock %d pdiv %d mult %d user %d\n",
02431             cur_timeout, timeout, exposure, dd_p->pclock_speed, pdiv,
02432             tmult, user_timeout);
02433 
02434     /*
02435      * sticking an 0.5 sec min in here because sometimes small cameras are
02436      * problematic
02437      */
02438     if (timeout < 500)
02439         timeout = 500;
02440 
02441     if (user_set)
02442     {
02443         edt_msg(DBG2, "  user set to %d - overriding auto\n", user_timeout);
02444 
02445         if (timeout > user_timeout && user_timeout != 0)
02446         {
02447             edt_msg(DBG2, "  Warning: exposure %d msecs user specified timeout %d msecs\n", dd_p->shutter_speed, user_timeout);
02448             edt_msg(DBG2, "  not automatically increased since user specified\n");
02449         }
02450     }
02451     else
02452     {
02453         int     targ;
02454 
02455         edt_msg(DBG2, "  setting picture timeout from %d to %d\n", cur_timeout, timeout);
02456         targ = timeout;
02457         ret = edt_set_rtimeout(pdv_p, targ);
02458     }
02459     return ret;
02460 }
02461 
02481 int
02482 pdv_set_gain(PdvDev * pdv_p, int value)
02483 {
02484     int     ret;
02485     char    cmdstr[64];
02486     Dependent *dd_p = pdv_p->dd_p;
02487 
02488     edt_msg(DBG2, "pdv_set_gain(%d)\n", value);
02489 
02490     dd_p->gain = value;
02491     ret = edt_set_dependent(pdv_p, dd_p);
02492 
02493     if ((strlen(dd_p->serial_gain) > 0)
02494         && (dd_p->serial_format == SERIAL_BINARY))
02495     {
02496         send_serial_binary_cmd(pdv_p, dd_p->serial_gain, value);
02497     }
02498 
02499     else if ((strlen(dd_p->serial_gain) > 0)
02500              && ((dd_p->serial_format == SERIAL_ASCII)
02501                  || (dd_p->serial_format == SERIAL_ASCII_HEX)))
02502     {
02503         if (dd_p->serial_gain[0] == ':')        /* pulnix 1300 format */
02504         {
02505             sprintf(cmdstr, "%s%x", dd_p->serial_gain, value);
02506             dd_p->serial_respcnt = 3;
02507         }
02508         if (dd_p->serial_gain[1] == '=')        /* thomson camelia format */
02509         {
02510             sprintf(cmdstr, "%s%x", dd_p->serial_gain, value);
02511         }
02512         else if (dd_p->serial_format == SERIAL_ASCII_HEX)
02513         {
02514             sprintf(cmdstr, "%s %02x", dd_p->serial_gain, value);
02515         }
02516         else                    /* kodak/other format */
02517             sprintf(cmdstr, "%s %d", dd_p->serial_gain, value);
02518         ret = pdv_serial_command_flagged(pdv_p, cmdstr, SCFLAG_NORESP);
02519         /*
02520          * pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout,
02521          * pdv_p->dd_p->serial_respcnt);
02522          */
02523         pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, 64);
02524         if (*pdv_p->dd_p->serial_response)
02525             pdv_serial_read(pdv_p, cmdstr, 63);
02526     }
02527 
02528     else if ((strncasecmp(dd_p->camera_class, "Hamamatsu", 9) == 0)
02529              && ((strncasecmp(dd_p->camera_model, "C8484", 5) == 0)
02530                  || (strncasecmp(dd_p->camera_model, "8484", 4) == 0)))
02531     {
02532         ret = pdv_set_gain_hc8484(pdv_p, value);
02533     }
02534 
02535     else if ((dd_p->camera_shutter_timing == SPECINST_SERIAL)
02536              || (dd_p->camera_shutter_speed == SPECINST_SERIAL))
02537     {
02538         ret = pdv_set_gain_specinst(pdv_p, value);
02539     }
02540     else if (dd_p->set_gain == SMD_SERIAL)      /* smd binary serial method */
02541     {
02542         ret = pdv_set_gain_smd(pdv_p, value);
02543     }
02544     else if ((strncasecmp(dd_p->camera_class, "Adimec", 6) == 0))
02545     {
02546         ret = pdv_set_gain_adimec(pdv_p, value);
02547     }
02548 
02549     else if ((strncasecmp(dd_p->camera_class, "PULNiX", 6) == 0)
02550              && ((strncasecmp(dd_p->camera_model, "TM-6710", 7) == 0)
02551                  || (strncasecmp(dd_p->camera_model, "TM-1020", 7) == 0)))
02552     {
02553         ret = pdv_set_gain_ptm6710_1020(pdv_p, value);
02554     }
02555 
02556     else if ((dd_p->set_gain == AIA_MC4)        /* mode cntl 4 method */
02557              && (dd_p->xilinx_rev >= 1 && dd_p->xilinx_rev <= 32))
02558     {
02559         u_int   util2 = edt_reg_read(pdv_p, PDV_UTIL2);
02560         u_int   mcl = edt_reg_read(pdv_p, PDV_MODE_CNTL);
02561 
02562         edt_reg_write(pdv_p, PDV_UTIL2, util2 & ~PDV_MC4);
02563         edt_reg_write(pdv_p, PDV_MODE_CNTL, dd_p->gain);
02564         edt_reg_write(pdv_p, PDV_UTIL2, util2 | PDV_MC4);
02565         edt_reg_write(pdv_p, PDV_MODE_CNTL, mcl);
02566     }
02567 
02568     edt_msg(DBG2, "pdv_set_gain returning %d\n", ret);
02569     return (ret);
02570 }
02571 
02575 pdv_set_gain_smd(PdvDev * pdv_p, int value)
02576 {
02577     char    buf[128];
02578     char    smd_config;
02579     int     smd_reg1;
02580     int     ret = 0;
02581 
02582     if (Smd_type == NOT_SET)
02583     {
02584         Smd_type = smd_read_reg(pdv_p, SMD_READ_CAMTYPE);
02585         if ((Smd_type & 0xfff) == 0xfff)        /* sometimes there's garbage
02586                                                  * at first; if so try again */
02587             Smd_type = smd_read_reg(pdv_p, SMD_READ_CAMTYPE);
02588     }
02589 
02590     switch (Smd_type)
02591     {
02592     case SMD_TYPE_4M4:
02593         buf[0] = (char) SMD_4M4_READ_R1;
02594         pdv_serial_binary_command(pdv_p, buf, 1);
02595         pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout,
02596                         pdv_p->dd_p->serial_respcnt);
02597         if (pdv_serial_read(pdv_p, buf, 63) == 1)
02598         {
02599             smd_config = buf[0];
02600 
02601             buf[0] = (char) SMD_4M4_WRITE_R1;
02602             pdv_serial_binary_command(pdv_p, buf, 1);
02603 
02604             if (value == 0)
02605                 smd_config &= ~SMD_4M4_R1_GAIN;
02606             else
02607                 smd_config |= SMD_4M4_R1_GAIN;
02608             buf[0] = smd_config;
02609             pdv_serial_binary_command(pdv_p, buf, 1);
02610             /* SMD doesn't resp but do a dummy wait to make sure its done */
02611             pdv_serial_wait(pdv_p, 100, 64);
02612         }
02613         else
02614             ret = -1;
02615         break;
02616 
02617     case SMD_TYPE_1M30P:
02618         buf[0] = (u_char) SMD_1M30P_REG_W_LS_GAIN;
02619         buf[1] = value & 0xff;
02620         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
02621 
02622         buf[0] = (u_char) SMD_1M30P_REG_W_MS_GAIN;
02623         buf[1] = (value & 0xff00) >> 8;
02624         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
02625 
02626         /* SMD doesn't respond but do a dmy wait to make sure its done */
02627         pdv_serial_wait(pdv_p, 100, 64);
02628         break;
02629 
02630     case SMD_TYPE_1M15P:
02631     case SMD_TYPE_6M3P:
02632         if ((smd_reg1 = smd_read_reg(pdv_p, SMD_1M15P_READ_R1)) == -1)
02633         {
02634             edt_msg(PDVWARN, "libpdv: no response from SMD R1 reg read\n");
02635             return -1;
02636         }
02637 
02638         buf[0] = (u_char) SMD_1M15P_WRITE_R1; /* same for 6M3P */
02639 
02640         /*
02641          * valid values for this camera are 0 or 1
02642          */
02643         if (value == 0)
02644             buf[1] = smd_reg1 &~ SMD_1M15P_R1_GAIN;
02645         else if (value == 1)
02646             buf[1] = smd_reg1 | SMD_1M15P_R1_GAIN;
02647         else return -1;
02648 
02649         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
02650         pdv_p->dd_p->gain = value;
02651 
02652         /* SMD doesn't respond but do a dmy wait to make sure its done */
02653         pdv_serial_wait(pdv_p, 100, 64);
02654         break;
02655     }
02656 
02657     return ret;
02658 }
02659 
02668 int
02669 pdv_set_gain_ch(PdvDev * pdv_p, int value, int chan)
02670 {
02671     int     ret = -1;
02672 
02673     /* ALERT -- no methods implemented since ddcam went away... */
02674     edt_msg(DBG2, "pdv_set_gain_ch(%d, [%c]) ret %d\n",
02675             value, (chan == 1) ? 'A' : (chan == 2) ? 'B' : '?', ret);
02676     return (ret);
02677 }
02678 
02697 int
02698 pdv_set_blacklevel(PdvDev * pdv_p, int value)
02699 {
02700     Dependent *dd_p = pdv_p->dd_p;
02701     int     ret;
02702 
02703     edt_msg(DBG2, "pdv_set_blacklevel(%d)\n", value);
02704 
02705     dd_p->level = value;
02706     ret = edt_set_dependent(pdv_p, dd_p);
02707 
02708     if (dd_p->set_offset == SMD_SERIAL) /* smd binary serial method */
02709         ret = pdv_set_blacklevel_smd(pdv_p, value);
02710 
02711     else if ((strncasecmp(dd_p->camera_class, "Adimec", 6) == 0))
02712     {
02713         ret = pdv_set_blacklevel_adimec(pdv_p, value);
02714     }
02715 
02716     else if ((strlen(dd_p->serial_offset) > 0)
02717              && (dd_p->serial_format == SERIAL_BINARY))
02718     {
02719         send_serial_binary_cmd(pdv_p, dd_p->serial_offset, value);
02720     }
02721 
02722     else if ((strlen(dd_p->serial_offset) > 0)
02723              && ((dd_p->serial_format == SERIAL_ASCII)
02724                  || (dd_p->serial_format == SERIAL_ASCII_HEX)))
02725     {
02726         char    cmdstr[128];
02727 
02728         if (dd_p->serial_format == SERIAL_ASCII_HEX)
02729             sprintf(cmdstr, "%s %02x", dd_p->serial_offset, value);
02730         else
02731             sprintf(cmdstr, "%s %d", dd_p->serial_offset, value);
02732         ret = pdv_serial_command_flagged(pdv_p, cmdstr, SCFLAG_NORESP);
02733         pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, pdv_p->dd_p->serial_respcnt);
02734         if (*pdv_p->dd_p->serial_response)
02735             pdv_serial_read(pdv_p, cmdstr, 63);
02736     }
02737     edt_msg(DBG2, "pdv_set_blacklevel() %d\n", ret);
02738     return (ret);
02739 }
02740 
02741 int pdv_set_blacklevel_smd(PdvDev * pdv_p, int value)
02742 {
02743     char    buf[128];
02744     int     ret = 0;
02745     int     tmpval = value & 0xfff;
02746     int     smd_reg2, smd_reg3;
02747 
02748     if (Smd_type == NOT_SET)
02749     {
02750         Smd_type = smd_read_reg(pdv_p, SMD_READ_CAMTYPE);
02751         if ((Smd_type & 0xfff) == 0xfff)        /* sometimes there's garbage
02752                                                  * at first; if so try again */
02753             Smd_type = smd_read_reg(pdv_p, SMD_READ_CAMTYPE);
02754     }
02755 
02756     switch (Smd_type)
02757     {
02758         case SMD_TYPE_4M4:
02759         case SMD_TYPE_BT25:
02760             break;
02761 
02762         case SMD_TYPE_1M30P:
02763             buf[0] = (u_char) SMD_1M30P_REG_W_LS_OFFSET;
02764             buf[1] = value & 0xff;
02765             pdv_serial_binary_command(pdv_p, (char *) buf, 2);
02766 
02767             buf[0] = (u_char) SMD_1M30P_REG_W_MS_OFFSET;
02768             buf[1] = (value & 0xff00) >> 8;
02769             pdv_serial_binary_command(pdv_p, (char *) buf, 2);
02770 
02771             /* SMD doesn't respond but do a dmy wait to make sure its done */
02772             pdv_serial_wait(pdv_p, 100, 64);
02773             break;
02774 
02775         case SMD_TYPE_1M15P:
02776             if ((smd_reg3 = smd_read_reg(pdv_p, SMD_1M15P_READ_R3)) == -1)
02777             {
02778                 edt_msg(PDVWARN, "libpdv: no response from Dalstar R3 reg read\n");
02779                 ret = -1;
02780             }
02781 
02782             smd_reg2 =  tmpval >> 4;
02783             smd_reg3 = (smd_reg3 & ~0x0f) | tmpval & 0x0f;
02784 
02785             /* write R3 */
02786             buf[0] = (u_char) SMD_1M15P_WRITE_R3;
02787             buf[1] = (u_char) smd_reg3;
02788             pdv_serial_binary_command(pdv_p, (char *) buf, 2);
02789 
02790             /* must write R2 last */
02791             buf[0] = (u_char) SMD_1M15P_WRITE_R2;
02792             buf[1] = (u_char) smd_reg2;
02793             pdv_serial_binary_command(pdv_p, (char *) buf, 2);
02794 
02795             /* SMD doesn't respond but do a dmy wait to make sure its done */
02796             pdv_serial_wait(pdv_p, 100, 64);
02797             break;
02798 
02799         default:
02800             ret = -1;
02801     }
02802 
02803     return ret;
02804 }
02805 
02814 int
02815 pdv_set_aperture(PdvDev * pdv_p, int value)
02816 {
02817     edt_msg(PDVWARN, "pdv_set_aperture is OBSOLETE\n");
02818     return (-1);
02819 }
02820 
02862 int
02863 pdv_set_binning(PdvDev * pdv_p, int xval, int yval)
02864 {
02865     int     ret = -1;
02866     int     newvskip, newhskip, newwidth, newheight;
02867     Dependent *dd_p = pdv_p->dd_p;
02868 
02869     if (((xval != 1) && (xval % 2)) || ((yval != 1) && (yval % 2)))
02870     {
02871         edt_msg(PDVWARN, "pdv_set_binning(%d, %d) -- invalid value\n", xval, yval);
02872         return -1;
02873     }
02874 
02875     edt_msg(DBG2, "pdv_set_binning(%d, %d)\n", xval, yval);
02876 
02877     if (strcmp(dd_p->serial_binning, "BIN") == 0)       /* DVC */
02878     {
02879         ret = pdv_set_binning_dvc(pdv_p, xval, yval);
02880     }
02881     else if (strcmp(dd_p->serial_binning, "B=") == 0)   /* ATMEL */
02882     {
02883         ret = pdv_set_binning_generic(pdv_p, xval - 1);
02884     }
02885     else if (*dd_p->serial_binning)     /* Generic */
02886     {
02887         /* wing it */
02888         ret = pdv_set_binning_generic(pdv_p, xval);
02889     }
02890     else
02891         return -1;
02892 
02893     if (ret)
02894         return ret;
02895 
02896     if (dd_p->binx < 1)
02897         dd_p->binx = 1;
02898     if (dd_p->biny < 1)
02899         dd_p->biny = 1;
02900 
02901     newwidth = (((pdv_get_width(pdv_p) * dd_p->binx) / xval) / 4) * 4;
02902     newheight = (((pdv_get_height(pdv_p) * dd_p->biny) / yval)) ;
02903 
02904     if (dd_p->roi_enabled)
02905     {
02906         newhskip = (dd_p->hskip * dd_p->binx) / xval;
02907         newvskip = (dd_p->vskip * dd_p->biny) / yval;
02908         ret = pdv_set_roi(pdv_p, newhskip, newwidth, newvskip, newheight);
02909     }
02910 
02911     if (!ret)
02912     {
02913         dd_p->binx = xval;
02914         dd_p->biny = yval;
02915     }
02916 
02917     return (ret);
02918 }
02919 
02925 int
02926 pdv_set_binning_generic(PdvDev * pdv_p, int value)
02927 {
02928     int     ret = 0;
02929     char    cmdstr[64];
02930     Dependent *dd_p = pdv_p->dd_p;
02931 
02932     if (dd_p->serial_binning[strlen(dd_p->serial_binning) - 1] == '=')  /* atmel */
02933         sprintf(cmdstr, "%s%d", dd_p->serial_binning, value);
02934     else
02935         sprintf(cmdstr, "%s %d", dd_p->serial_binning, value);
02936     pdv_serial_command_flagged(pdv_p, cmdstr, SCFLAG_NORESP);
02937 
02938     return (0);
02939 }
02940 
02941 
02954 int
02955 pdv_get_exposure(PdvDev * pdv_p)
02956 {
02957     edt_msg(DBG2, "pdv_get_exposure() %d\n", pdv_p->dd_p->shutter_speed);
02958 
02959     return (pdv_p->dd_p->shutter_speed);
02960 }
02961 
02962 void
02963 pdv_set_defaults(PdvDev * pdv_p)
02964 {
02965     Dependent *dd_p = pdv_p->dd_p;
02966 
02967     if (dd_p->default_shutter_speed != NOT_SET)
02968         pdv_set_exposure(pdv_p, dd_p->default_shutter_speed);
02969     if (dd_p->default_gain != NOT_SET)
02970         pdv_set_gain(pdv_p, dd_p->default_gain);
02971     if (dd_p->default_offset != NOT_SET)
02972         pdv_set_blacklevel(pdv_p, dd_p->default_offset);
02973 }
02974 
02986 pdv_read_response(PdvDev * pdv_p, char *buf)
02987 {
02988     int     len;
02989 
02990     /*
02991      * serial_timeout comes from the config file, or default of 1 sec
02992      */
02993     len = pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, 2048);
02994     if (len)
02995         pdv_serial_read(pdv_p, buf, len);
02996     return len;
02997 }
02998 
02999 
03014 int
03015 pdv_get_gain(PdvDev * pdv_p)
03016 {
03017     edt_msg(DBG2, "pdv_get_gain() %d\n", pdv_p->dd_p->gain);
03018 
03019     return (pdv_p->dd_p->gain);
03020 }
03021 
03022 
03035 int
03036 pdv_get_blacklevel(PdvDev * pdv_p)
03037 {
03038     edt_msg(DBG2, "pdv_get_blacklevel() %d\n", pdv_p->dd_p->level);
03039 
03040     return (pdv_p->dd_p->level);
03041 }
03042 
03051 int
03052 pdv_get_aperture(PdvDev * pdv_p)
03053 {
03054     edt_msg(PDVWARN, "pdv_get_aperture is OBSOLETE\n");
03055     return (-1);
03056 }
03057 
03068 void
03069 pdv_invert(PdvDev * pdv_p, int val)
03070 {
03071     u_int   data_path;
03072     int     ret;
03073 
03074     edt_msg(DBG2, "pdv_invert()\n");
03075 
03076     if (pdv_p->devid == PDVFOI_ID)
03077     {
03078         char    buf[64];
03079 
03080         pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, pdv_p->dd_p->serial_respcnt);
03081         if (*pdv_p->dd_p->serial_response)
03082             ret = pdv_serial_read(pdv_p, buf, 63);
03083     }
03084 
03085     /* data_path = edt_reg_read(pdv_p, PDV_DATA_PATH); */
03086     data_path = pdv_p->dd_p->datapath_reg;
03087 
03088     edt_msg(DBG2, "pdv_invert(%d)\n", val);
03089 
03090     if (val)
03091         data_path |= PDV_INVERT;
03092     else
03093         data_path &= ~PDV_INVERT;
03094 
03095     edt_reg_write(pdv_p, PDV_DATA_PATH, data_path);
03096     pdv_p->dd_p->datapath_reg = data_path;
03097 }
03098 
03104 u_short
03105 pdv_get_interlaced(PdvDev * pdv_p)
03106 
03107 {
03108     edt_msg(DBG2, "pdv_get_interlaced() %u\n", pdv_p->dd_p->interlace);
03109 
03110     return (pdv_p->dd_p->interlace);
03111 }
03112 
03135 int
03136 pdv_force_single(PdvDev * pdv_p)
03137 {
03138     return pdv_p->dd_p->force_single;
03139 }
03140 
03148 int
03149 pdv_variable_size(PdvDev * pdv_p)
03150 {
03151     return pdv_p->dd_p->variable_size;
03152 }
03153 
03154 
03161 int
03162 pdv_enable_lock(PdvDev * pdv_p, int flag)
03163 {
03164     Dependent *dd_p = pdv_p->dd_p;
03165     int     ret;
03166 
03167     switch (dd_p->lock_shutter)
03168     {
03169     case KODAK_AIA_MCL:
03170         {
03171             int     mcl = edt_reg_read(pdv_p, PDV_MODE_CNTL);
03172 
03173             if (flag)
03174                 mcl |= PDV_AIA_MC3;
03175             else
03176                 mcl &= ~PDV_AIA_MC3;
03177 
03178             edt_reg_write(pdv_p, PDV_MODE_CNTL, mcl);
03179             ret = 0;
03180             break;
03181         }
03182     case KODAK_AIA_SER:
03183         {
03184             if (flag)
03185                 ret = pdv_serial_command(pdv_p, "SHE OF");
03186             else
03187                 ret = pdv_serial_command(pdv_p, "SHE ON");
03188 
03189             break;
03190         }
03191     case KODAK_SER_14I:
03192         {
03193             if (flag)
03194                 ret = pdv_serial_command(pdv_p, "SHE FO");
03195             else
03196                 ret = pdv_serial_command(pdv_p, "SHE ON");
03197             break;
03198         }
03199     case HAM_4880:
03200         {
03201             if (flag)
03202                 ret = pdv_serial_command(pdv_p, "ASH O");
03203             else
03204                 ret = pdv_serial_command(pdv_p, "ASH A");
03205             break;
03206         }
03207     }
03208     return (ret);
03209 }
03210 
03211 
03231 int
03232 pdv_serial_read_nullterm(PdvDev * pdv_p, char *buf, int size, int nullterm)
03233 {
03234 #define PKT_OVERHEAD 2
03235 #define PKT_SIZE_MAX 15
03236 
03237     int     bytesReturned;
03238     int     total = 0;
03239     Dependent *dd_p;
03240 
03241     if (pdv_p == NULL || pdv_p->dd_p == NULL)
03242         return 0;
03243 
03244     dd_p = pdv_p->dd_p;
03245 
03246     if (buf == NULL || pdv_p == NULL || size == 0)
03247         return (-1);
03248 
03249     if (pdv_p->devid == PDVFOI_ID)
03250     {
03251         char    tmpbuf[256];
03252 
03253         bytesReturned = edt_get_msg(pdv_p, tmpbuf, 256);
03254         if (bytesReturned <= PKT_OVERHEAD)
03255             return (0);
03256         if (Pdv_debug)
03257         {
03258             int     i, num = bytesReturned;
03259 
03260             if (num > 16)       /* limit number of bytes printed to 16 */
03261                 num = 16;
03262             edt_msg(DBG2, "pdv_serial_read(<");
03263             for (i = 0; i < num; i++)
03264             {
03265                 edt_msg(DBG2, "%02x", (u_char) tmpbuf[i]);
03266                 if (i + 1 < num)
03267                     edt_msg(DBG2, ", ");
03268                 else
03269                     break;
03270             }
03271             edt_msg(DBG2, ">, %d-%d\n", bytesReturned, size);
03272         }
03273         if (bytesReturned > size)
03274         {
03275             memcpy(buf, &tmpbuf[PKT_OVERHEAD], size);
03276             edt_msg(DBG2, "pdv_serial_read(%d) %d\n", size, bytesReturned);
03277             return (size);
03278         }
03279         else
03280         {
03281             bytesReturned -= PKT_OVERHEAD;
03282             memcpy(buf, &tmpbuf[PKT_OVERHEAD], bytesReturned);
03283             if (nullterm)
03284                 buf[bytesReturned] = 0;
03285             edt_msg(DBG2, "pdv_serial_read(%d) %d\n", size, bytesReturned);
03286             return (bytesReturned);
03287         }
03288     }
03289 
03290 #if 0
03291     if (!pdv_get_width(pdv_p))
03292     {
03293         edt_msg(DBG2, "warning - serial_read called with uninitialized camera\n");
03294         return (0);
03295     }
03296 #endif
03297 
03298     bytesReturned = edt_get_msg(pdv_p, buf, size);
03299         assert(bytesReturned <= size);
03300 
03301     if (nullterm)
03302         buf[bytesReturned] = 0;
03303 
03304     if (Pdv_debug)
03305     {
03306         int     i, num = bytesReturned;
03307 
03308         if (num > 16)           /* limit number of bytes printed to 16 */
03309             num = 16;
03310         edt_msg(DBG2, "pdv_serial_read(<");
03311         for (i = 0; i < num; i++)
03312         {
03313             edt_msg(DBG2, "%02x", (u_char) buf[i]);
03314             if (i + 1 < num)
03315                 edt_msg(DBG2, ", ");
03316             else
03317                 break;
03318         }
03319         edt_msg(DBG2, ">, %d)\n", size);
03320     }
03321     return bytesReturned;
03322 }
03323 
03355 int
03356 pdv_serial_read(PdvDev * pdv_p, char *buf, int count)
03357 {
03358 
03359         return pdv_serial_read_nullterm(pdv_p,buf,count,TRUE);
03360 }
03361 
03368 int
03369 pdv_send_msg(PdvDev *ed, int chan, char *buf, int size)
03370 {
03371     int i, ret = 0;
03372     int pause = ed->dd_p->pause_for_serial;
03373     char bbuf[32];
03374 
03375     /* sleep between bytes if indicated */
03376     if (pause)
03377     {
03378         for (i=0; i<size; i++)
03379         {
03380             bbuf[0] = buf[i];
03381             edt_msleep(ed->dd_p->pause_for_serial);
03382             if ((ret = edt_send_msg(ed, chan, bbuf, 1)) != 0)
03383                 return ret;
03384         }
03385         return ret;
03386     }
03387     else return edt_send_msg(ed, chan, buf, size);
03388 }
03389 
03405 int
03406 pdv_serial_write_single_block(PdvDev * pdv_p, char *buf, int size)
03407 {
03408     int     ret;
03409     Dependent *dd_p;
03410 
03411     if (size == 0)
03412         return (-1);
03413 
03414     if (Pdv_debug)
03415     {
03416         int     i, num = size;
03417 
03418         if (num > 16)           /* limit number of bytes printed to 16 */
03419             num = 16;
03420         edt_msg(DBG2, "pdv_serial_write_single_block(<");
03421         for (i = 0; i < num; i++)
03422         {
03423             edt_msg(DBG2, "%02x", (u_char) buf[i]);
03424             if (i + 1 < num)
03425                 edt_msg(DBG2, ", ");
03426             else
03427                 break;
03428         }
03429         edt_msg(DBG2, ">, %d)\n", size);
03430     }
03431 
03432     if (buf == NULL || pdv_p == NULL || pdv_p->dd_p == NULL)
03433         return (-1);
03434     dd_p = pdv_p->dd_p;
03435 
03436     if (pdv_p->devid == PDVFOI_ID)
03437     {
03438         ret = pdv_send_msg(pdv_p, pdv_p->foi_unit, buf, size);
03439         return (ret);
03440     }
03441     else
03442     {
03443         ret = pdv_send_msg(pdv_p, pdv_p->channel_no, buf, size);
03444         return (ret);
03445     }
03446 }
03447 
03456 int
03457 pdv_serial_write_available(PdvDev *pdv_p)
03458 
03459 {
03460 
03461     int avail;
03462 
03463     edt_ioctl(pdv_p, EDTG_SERIAL_WRITE_AVAIL, &avail);
03464 
03465     return avail;
03466 
03467 }
03468 
03469 static int pdv_serial_block_size = 512;
03470 
03476 void pdv_set_serial_block_size(int newsize)
03477 {
03478         pdv_serial_block_size = newsize;
03479 }
03480 
03487 int
03488 pdv_get_serial_block_size()
03489 {
03490     return pdv_serial_block_size;
03491 }
03492 
03496 int
03497 pdv_serial_read_enable(PdvDev *pdv_p)
03498 
03499 {
03500 
03501     edt_reg_or(pdv_p, PDV_SERIAL_DATA_CNTL,
03502             PDV_EN_TX | PDV_EN_RX |
03503             PDV_EN_RX_INT | PDV_EN_DEV_INT);
03504 
03505     edt_reg_or(pdv_p, EDT_DMA_INTCFG, EDT_RMT_EN_INTR | EDT_PCI_EN_INTR) ; 
03506 
03507     return 0;
03508 }
03509 
03526 int
03527 pdv_serial_write(PdvDev *pdv_p, char *buf, int size)
03528 
03529 {
03530     int avail;
03531     int left = size;
03532     int ret = 0;
03533     int offset = 0;
03534     int speed = pdv_get_baud(pdv_p);
03535     int sleepval;
03536     int chunk = pdv_serial_block_size;
03537 
03538     if (speed != 0)
03539         sleepval = speed/10;
03540     else
03541         sleepval = 10;
03542 
03543     sleepval = (chunk * 1000) / sleepval; /* time to send chunk chars */
03544 
03545     avail = pdv_serial_write_available(pdv_p);
03546     if (avail > size)
03547     {
03548         return pdv_serial_write_single_block(pdv_p, buf, size);
03549     }
03550     else
03551     {
03552         left -= avail;
03553         offset += avail;
03554 
03555 #ifdef DBG_SERIAL
03556         printf("Writing %d chars\n", avail);
03557 #endif
03558 
03559         ret = pdv_serial_write_single_block(pdv_p, buf, avail);
03560 
03561         if (ret != 0)
03562                 return ret;
03563         while (left > 0)
03564         {
03565             edt_msleep(sleepval);
03566             avail = pdv_serial_write_available(pdv_p);
03567             if (avail > 0)
03568             {
03569                 if ( avail > left)
03570                 {
03571                     avail = left;
03572                     left = 0;
03573                 }
03574                 else
03575                 {
03576                     left -= avail;
03577                 }
03578 
03579 #ifdef DBG_SERIAL
03580                 printf("Writing %d chars\n", avail);
03581 #endif
03582                 ret = pdv_serial_write_single_block(pdv_p, buf+offset, avail);
03583                 if (ret != 0)
03584                     return ret;
03585                     offset += avail;
03586 
03587             }
03588         }
03589     }
03590     return 0;
03591 }
03592 
03609 int
03610 pdv_serial_read_blocking(PdvDev *pdv_p, char *buf, int size)
03611 
03612 {
03613     int left = size;
03614     int ret = 0;
03615         int offset = 0;
03616 
03617 
03618         int avail = 1024;
03619         int speed = pdv_get_baud(pdv_p);
03620         int sleepval;
03621         int chunk = pdv_serial_block_size;
03622 
03623         if (speed != 0)
03624                 sleepval = speed/10;
03625         else
03626                 sleepval = 10;
03627 
03628         sleepval = (chunk * 1000) / sleepval; /* time to send chunk chars */
03629 
03630     if (avail > size)
03631     {
03632                 sleepval = (size * 1000) / sleepval;
03633 
03634                 pdv_serial_wait(pdv_p, sleepval, size);
03635 
03636                 return pdv_serial_read(pdv_p, buf, size);
03637     }
03638     else
03639     {
03640 
03641                 while (left > 0)
03642                 {
03643                         avail = pdv_serial_wait(pdv_p, sleepval, chunk);
03644                         if (avail)
03645                         {
03646                                 if ( avail > left)
03647                                 {
03648                                         avail = left;
03649                                         left = 0;
03650                                 }
03651                                 else
03652                                 {
03653                                         left -= avail;
03654                                 }
03655 
03656 #ifdef DBG_SERIAL
03657                                 printf("Reading %d chars total = %d\n", avail, offset + avail);
03658 #endif
03659                                 ret = pdv_serial_read(pdv_p, buf+offset, avail);
03660                                 offset += avail;
03661 
03662                         }
03663 
03664 
03665                 }
03666 
03667     }
03668 
03669     return 0;
03670 
03671 }
03672 
03673 
03717 int
03718 pdv_serial_command(PdvDev * pdv_p, char *cmd)
03719 {
03720         /* older comment:
03721          * Sends a serial AIA command convenience wrapper for pdv_serial_write()
03722          * -- takes the command string and adds the '\r' and deals with the
03723          * string length issue... Prepends a 'c if FOI. Because of the FOI
03724          * issue, applications should ALWAYS use this or
03725          * pdv_serial_binary_command instead of calling pdv_serial_write
03726          * directly.
03727          * 
03728          * UNLESS -- serial_format is SERIAL_PULNIX_1010, in which case it prepends an
03729          * STX (0x2) and appends an ETX (0x3)
03730          */
03731     return pdv_serial_command_flagged(pdv_p, cmd, 0);
03732 }
03733 
03750 int
03751 pdv_serial_command_flagged(PdvDev * pdv_p, char *cmd, u_int flag)
03752 {
03753     char    *buf;
03754     int     ret;
03755     int     i;
03756     size_t     len=0;
03757     int     bufsize=8; /* arbitrary but should handle whatever extra is tacked on below */
03758     char    *p = cmd;
03759 
03760     if (pdv_p == NULL || pdv_p->dd_p == NULL)
03761         return -1;
03762 
03763     /* find the size (new, was fixed @ 256, now dynamic) */
03764     while (*p++)
03765         ++bufsize;
03766     buf = (char *)malloc(bufsize+16);
03767     /* 16 is arbitrary, to allow for serial_prefix/serial_term */
03768 
03769     /* prepend "c" for FOI */
03770     if (pdv_p->devid == PDVFOI_ID)
03771     {
03772         buf[len++] = 'c';
03773 
03774         /* 't' says don't wait for response */
03775         if (flag & SCFLAG_NORESP)
03776             buf[len++] = 't';
03777         buf[len++] = ' ';
03778     }
03779 
03780     /* new:  serial_prefix -- prepend if nonzero */
03781     if (*pdv_p->dd_p->serial_prefix)
03782     {
03783         strcpy(&(buf[len]), pdv_p->dd_p->serial_prefix);
03784         len += strlen(pdv_p->dd_p->serial_prefix);
03785     }
03786 
03787     /* strip off  CR or LF, then add prepend/append STX/ETX */
03788     if (pdv_p->dd_p->serial_format == SERIAL_PULNIX_1010)
03789     {
03790         buf[len++] = 0x02;      /* prepend STX */
03791         for (i = 0; i < bufsize; i++)
03792             if (cmd[i] == '\r' || cmd[i] == '\n' || cmd[i] == 0)
03793                 break;
03794             else
03795                 buf[len++] = cmd[i];
03796         buf[len++] = 0x03;      /* append ETX */
03797     }
03798     else
03799     {
03800         /* strip off  CR or LF, then add serial_term */
03801 
03802         for (i = 0; i < bufsize; i++)
03803         {
03804             if (cmd[i] == '\r' || cmd[i] == '\n' || cmd[i] == 0)
03805                 break;
03806             else
03807                 buf[len++] = cmd[i];
03808         }
03809         /* ALERT! need to change for FOI if \\n! */
03810         sprintf(&(buf[len]), "%s", pdv_serial_term(pdv_p));
03811         len += strlen(pdv_serial_term(pdv_p));
03812     }
03813 
03814     if (Pdv_debug)
03815         debug_print_serial_command(buf);
03816     ret = pdv_serial_write(pdv_p, buf, len);
03817 
03818         free(buf);
03819     return (ret);
03820 }
03821 
03830 char   *
03831 pdv_serial_term(PdvDev * pdv_p)
03832 {
03833     return pdv_p->dd_p->serial_term;
03834 }
03835 
03844 char   *
03845 pdv_serial_prefix(PdvDev * pdv_p)
03846 {
03847     return pdv_p->dd_p->serial_prefix;
03848 }
03849 
03864 void
03865 pdv_set_serial_delimiters(PdvDev *pdv_p, char *prefix, char *term)
03866 
03867 {
03868     if (prefix)
03869         strncpy(pdv_p->dd_p->serial_prefix,prefix, sizeof(pdv_p->dd_p->serial_prefix)-1);
03870     else
03871         pdv_p->dd_p->serial_prefix[0] = 0;
03872 
03873     if (term)
03874         strncpy(pdv_p->dd_p->serial_term,term, sizeof(pdv_p->dd_p->serial_term)-1);
03875     else
03876         pdv_p->dd_p->serial_term[0] = 0;
03877     
03878     edt_set_dependent(pdv_p,pdv_p->dd_p);
03879 }
03880 
03881 
03882 /* debug print ASCII serial command string, from pdv_serial_command */
03883 static void
03884 debug_print_serial_command(char *cmd)
03885 {
03886     char    tmpbuf[256];
03887     char   *p = cmd;
03888     char   *pp = tmpbuf;
03889     int    len=0;
03890 
03891     while (*p != '\0')
03892     {
03893         if (*p == 0x02)
03894         {
03895             sprintf(pp, "<0x2>");
03896             pp += 5;
03897             len += 5;
03898             ++p;
03899         }
03900         else if (*p == 0x03)
03901         {
03902             sprintf(pp, "<0x3>");
03903             pp += 5;
03904             len += 5;
03905             ++p;
03906         }
03907 
03908         else if (*p == '\r')
03909         {
03910             sprintf(pp, "\\r");
03911             pp += 2;
03912             len += 2;
03913             ++p;
03914         }
03915         else if (*p == '\n')
03916         {
03917             sprintf(pp, "\\n");
03918             pp += 2;
03919             len += 2;
03920             ++p;
03921         }
03922         else
03923         {
03924             *(pp++) = *(p++);
03925             ++len ;
03926         }
03927         if (len > 250) /* arbitrary max, just bail out so we don't crash */
03928             break;
03929     }
03930     *pp = '\0';
03931     edt_msg(DBG2, "pdv_serial_command(\"%s\")\n", tmpbuf);
03932 }
03933 
03964 int
03965 pdv_serial_binary_command(PdvDev * pdv_p, char *cmd, int len)
03966 {
03967     return pdv_serial_binary_command_flagged(pdv_p, cmd, len, 0);
03968 }
03969 
03970 
03977 int
03978 pdv_send_basler_frame(PdvDev * pdv_p, u_char *cmd, int len)
03979 {
03980     int i;
03981     u_char frame[128];
03982     u_char *p = frame;
03983     u_char bcc = 0;
03984 
03985     *p++ = 0x02;
03986     for (i=0; i<len; i++)
03987     {
03988         bcc ^= cmd[i];
03989         *p++ = cmd[i];
03990     }
03991     *p++ = bcc;
03992     *p++ = 0x03;
03993 
03994     return pdv_serial_binary_command_flagged(pdv_p, (char *)frame, len+3, 0);
03995 }
03996 
04003 int
04004 pdv_read_basler_frame(PdvDev * pdv_p, u_char *frame, int len)
04005 {
04006     int n, nn;
04007     char tmpbuf[128];
04008     char *p;
04009 
04010     n = pdv_serial_wait(pdv_p, 500, len);
04011     if (n < 1)
04012         return 0;
04013 
04014     nn = pdv_serial_read(pdv_p, tmpbuf, n);
04015 
04016     if (tmpbuf[0] == 0x06) /* ACK */
04017     {
04018         frame[0] = 0x06;
04019         return 1;
04020     }
04021 
04022     if (tmpbuf[0] == 0x15) /* ACK */
04023     {
04024         frame[0] = 0x06;
04025         return 1;
04026     }
04027 
04028     if (tmpbuf[0] == 0x02)
04029     {
04030         p = &tmpbuf[nn];
04031         n = pdv_serial_wait(pdv_p, 50, len);
04032         pdv_serial_read(pdv_p, p, n);
04033     /* ALERT -- FINISH this! */
04034     }
04035     return n;
04036 }
04037 
04053 int
04054 pdv_send_duncan_frame(PdvDev * pdv_p, u_char *cmdbuf, int size)
04055 {
04056     int i;
04057     u_char frame[128];
04058     u_char *p = frame;
04059 
04060     *p++ = 0x02;
04061     for (i=0; i<size; i++)
04062         *p++ = cmdbuf[i];
04063 
04064     CheckSumMessage(frame);
04065 
04066    return pdv_serial_binary_command_flagged(pdv_p, (char *)frame, size+2, 0);
04067 }
04068 
04069 static void
04070 CheckSumMessage(unsigned char *msg)
04071 {
04072     unsigned short length; 
04073     unsigned char csum = 0;
04074 
04075     msg++;         
04076     length = *msg++;
04077     length += *msg++ << 8;
04078     if (length > 0)
04079     {
04080         for (; length > 0; length--)
04081             csum += *msg++;
04082         *msg = -csum;
04083     }
04084 }
04085 
04086 
04099 int
04100 pdv_read_duncan_frame(PdvDev * pdv_p, u_char *frame)
04101 {
04102     int n, nn;
04103     u_short length;
04104 
04105     /* read the STX and 2-byte length */
04106     n = pdv_serial_wait(pdv_p, 500, 3);
04107     if (n < 3)
04108         return 0;
04109 
04110     nn = pdv_serial_read(pdv_p, (char *)frame, 3);
04111 
04112     length = (u_short)frame[1] + (u_short)(frame[2] << 8);
04113 
04114     if (length)
04115         n = pdv_serial_wait(pdv_p, 1000, length+1);
04116 
04117     if (n)
04118         pdv_serial_read(pdv_p, (char *)(&frame[3]), n);
04119 
04120     return n+nn;
04121 }
04122 
04146 int
04147 pdv_serial_binary_command_flagged(PdvDev * pdv_p, char *cmd, int len, u_int flag)
04148 {
04149     char    *buf;
04150     int     ret;
04151     int     i;
04152     int     tmplen = 0;
04153 
04154     edt_msg(DBG2, "pdv_serial_binary_command()\n");
04155 
04156     if (pdv_p == NULL || pdv_p->dd_p == NULL)
04157         return -1;
04158 
04159     if ((buf = (char *)malloc(len)) == NULL)
04160         return -1;
04161 
04162     /* prepend "c" for FOI */
04163     if (pdv_p->devid == PDVFOI_ID)
04164     {
04165         buf[tmplen++] = 'c';
04166         if (flag & SCFLAG_NORESP)
04167             buf[tmplen++] = 't';
04168         buf[tmplen++] = ' ';
04169     }
04170 
04171     /* don't include CR or LF */
04172     for (i = 0; i < len; i++)
04173     {
04174         buf[tmplen++] = cmd[i];
04175     }
04176     ret = pdv_serial_write(pdv_p, buf, tmplen);
04177     return (ret);
04178 }
04179  /* end serial */
04181 
04209 int
04210 pdv_read(PdvDev * pdv_p, unsigned char *buf, unsigned long size)
04211 {
04212     Dependent *dd_p;
04213     unsigned long newsize;
04214     int     readsize;
04215     int     dosi = 0;
04216     unsigned char *tbuf;
04217 
04218 
04219     edt_msg(DBG2, "pdv_read()\n");
04220 
04221     pdv_setup_dma(pdv_p);
04222 
04223     if (pdv_p->dd_p->start_delay)
04224                 edt_msleep(pdv_p->dd_p->start_delay);
04225 
04226 
04227     if (pdv_specinst_serial_triggered(pdv_p))
04228     {
04229                 edt_msg(PDVWARN, "libpdv invalid combination: SPECINST_SERIAL/pdv_read/i/f trigger");
04230                 edt_msg(PDVWARN, "should use pdv_start_image() or external trigger");
04231     }
04232 
04233     if (pdv_p == NULL || pdv_p->dd_p == NULL)
04234         return -1;
04235 
04236     dd_p = pdv_p->dd_p;
04237 
04238     if (pdv_p->devid == DMY_ID)
04239     {
04240                 pdv_dmy_data(buf, dd_p->width, dd_p->height, dd_p->depth);
04241                 if (dd_p->markras)
04242                     pdv_mark_ras(buf, dd_p->rascnt,
04243                          dd_p->width, dd_p->height, dd_p->markrasx, dd_p->markrasy);
04244                 if (dd_p->markbin)
04245                         pdv_mark_bin(buf, dd_p->rascnt, dd_p->width, dd_p->height, 4, 0);
04246                 if (dd_p->markbin || dd_p->markras) dd_p->rascnt++ ;
04247                 printf("pdv_read rascnt %d\n",dd_p->rascnt) ;
04248                 return (size);
04249     }
04250 
04251     readsize = pdv_get_dmasize(pdv_p);
04252         
04253     if (dd_p->swinterlace)
04254     {
04255                 pdv_alloc_tmpbuf(pdv_p);
04256 
04257                 readsize = pdv_get_dmasize(pdv_p);
04258 
04259     }
04260 
04261     /*
04262      * specify register and value to set after starting dma
04263      */
04264     edt_startdma_reg(pdv_p, PDV_CMD, PDV_ENABLE_GRAB);
04265     if (edt_get_firstflush(pdv_p) != EDT_ACT_KBS)
04266         edt_set_firstflush(pdv_p, EDT_ACT_ONCE);
04267 
04268 
04269     if (dd_p->slop)
04270     {
04271                 edt_msg(DBG2, "adjusting readsize %x by slop %x to %x\n",
04272                 readsize, dd_p->slop, readsize - dd_p->slop);
04273         readsize -= dd_p->slop;
04274     }
04275 
04276     if (dd_p->header_size && dd_p->header_dma)
04277     {
04278         readsize += dd_p->header_size;
04279     }
04280 
04281     if (dd_p->swinterlace)
04282     {
04283         if (pdv_process_inplace(pdv_p))
04284             tbuf = buf;
04285         else
04286             tbuf = pdv_p->tmpbuf;
04287 
04288         newsize = edt_read(pdv_p, tbuf, readsize);
04289         dd_p->last_raw = tbuf;
04290         dd_p->last_image = buf;
04291     }
04292     else
04293     {
04294         tbuf = buf;
04295         newsize = edt_read(pdv_p, buf, readsize);
04296         dd_p->last_raw = buf;
04297         dd_p->last_image = buf;
04298     }
04299 
04300     dd_p->rascnt = 1;
04301     if (dd_p->markras)
04302         pdv_mark_ras(buf, dd_p->rascnt++, dd_p->width, dd_p->height,
04303                      dd_p->markrasx, dd_p->markrasy);
04304 
04305     size = newsize;
04306 
04307     /* edt_startdma_reg(pdv_p, 0, 0) ; */
04308 
04309     edt_msg(DBG2, "swinterlace %d\n", dd_p->swinterlace);
04310 
04311     pdv_deinterlace(pdv_p, dd_p, tbuf, buf);
04312 
04313   
04314 
04315     return (size);
04316 }
04317 
04318 
04333 unsigned char *
04334 pdv_image(PdvDev * pdv_p)
04335 {
04336     edt_msg(DBG2, "pdv_image()\n");
04337 
04338     pdv_start_images(pdv_p, 1);
04339     return pdv_wait_images(pdv_p, 1);
04340 }
04341 
04342 
04353 unsigned char *
04354 pdv_image_raw(PdvDev * pdv_p)
04355 {
04356     edt_msg(DBG2, "pdv_image()\n");
04357 
04358     pdv_start_images(pdv_p, 1);
04359     return pdv_wait_images_raw(pdv_p, 1);
04360 }
04361 
04370 void
04371 pdv_start_image(PdvDev * pdv_p)
04372 {
04373     edt_msg(DBG2, "pdv_start_image()\n");
04374 
04375     pdv_start_images(pdv_p, 1);
04376 }
04377 
04378 
04391 void
04392 pdv_start_images(PdvDev * pdv_p, int count)
04393 {
04394 
04395     edt_msg(DBG2, "pdv_start_images(%d) %d\n", count, pdv_p->dd_p->started_continuous);
04396 
04397     if (pdv_p->dd_p->start_delay)
04398         edt_msleep(pdv_p->dd_p->start_delay);
04399 
04400     /* automatically alloc 1 buffer if none allocated */
04401     if (pdv_p->ring_buffer_numbufs < 1)
04402         pdv_multibuf(pdv_p, 1);
04403 
04404 /* 
04405     if (pdv_p->devid == DMY_ID)
04406     {
04407         dmystarted += count ;
04408         return;
04409     }
04410 */
04411     if (!pdv_p->dd_p->started_continuous)
04412     {
04413         pdv_setup_continuous(pdv_p);
04414     }
04415     if (pdv_force_single(pdv_p) && (count > 1))
04416     {
04417         edt_msg(PDVWARN,
04418           "pdv_start_images(): %d buffers requested; should only\n", count);
04419         edt_msg(PDVWARN,
04420          "start one at a time when 'force_single' is set in config file\n");
04421         count = 1;
04422     }
04423 
04424 
04425     edt_start_buffers(pdv_p, count);
04426 
04427     if (pdv_specinst_serial_triggered(pdv_p))
04428         pdv_trigger_specinst(pdv_p);
04429 }
04430 
04431 
04469 unsigned char *
04470 pdv_wait_image(PdvDev * pdv_p)
04471 {
04472     edt_msg(DBG2, "pdv_wait_image()\n");
04473 
04474     return pdv_wait_images(pdv_p, 1);
04475 }
04476 
04502 unsigned char *
04503 pdv_wait_image_raw(PdvDev * pdv_p)
04504 {
04505     edt_msg(DBG2, "pdv_wait_image()\n");
04506 
04507     return pdv_wait_images_raw(pdv_p, 1);
04508 }
04509 
04510 
04542 unsigned char *
04543 pdv_wait_image_timed(PdvDev * pdv_p, u_int * timep)
04544 {
04545      return pdv_wait_image_timed_raw(pdv_p, timep, FALSE);
04546 }
04547 
04580 unsigned char *
04581 pdv_wait_image_timed_raw(PdvDev * pdv_p, u_int * timep, int doRaw)
04582 {
04583     u_char *ret;
04584 
04585     edt_msg(DBG2, "pdv_wait_image()\n");
04586 
04587     if (doRaw)
04588                 ret = pdv_wait_images_raw(pdv_p, 1);
04589         else
04590                 ret = pdv_wait_images(pdv_p, 1);
04591     
04592         edt_get_timestamp(pdv_p, timep, pdv_p->donecount - 1);
04593     return (ret);
04594 }
04595 
04634 unsigned char *
04635 pdv_wait_images_timed_raw(PdvDev * pdv_p, int count, u_int * timep, int doRaw)
04636 {
04637     u_char *ret;
04638 
04639     edt_msg(DBG2, "pdv_wait_images_timed_raw(count=%d, doRaw=%d)\n", 
04640                     count, doRaw);
04641 
04642         if (doRaw)
04643                 ret = pdv_wait_images_raw(pdv_p, count);
04644         else
04645                 ret = pdv_wait_images(pdv_p, count);
04646 
04647     edt_get_timestamp(pdv_p, timep, pdv_p->donecount - 1);
04648     return (ret);
04649 }
04650 
04671 unsigned char *
04672 pdv_wait_images_timed(PdvDev * pdv_p, int count, u_int * timep)
04673 {
04674      return pdv_wait_images_timed_raw(pdv_p, count, timep, FALSE);
04675 }
04676 
04681 unsigned char *
04682 pdv_last_image_timed_raw(PdvDev * pdv_p, u_int * timep, int doRaw)
04683 {
04684     return pdv_wait_last_image_timed_raw(pdv_p, timep, doRaw);
04685 
04686 }
04687 
04710 unsigned char *
04711 pdv_wait_last_image_timed_raw(PdvDev * pdv_p, u_int * timep, int doRaw)
04712 {
04713     u_char *ret;
04714     int     donecount;
04715     int     last_wait;
04716     int     delta;
04717 
04718     donecount = edt_done_count(pdv_p);
04719     last_wait = pdv_p->donecount;
04720 
04721     edt_msg(DBG2, "pdv_wait_last_image_timed() last %d cur %d\n",
04722             last_wait, donecount);
04723 
04724     delta = donecount - last_wait;
04725 
04726     if (delta == 0)
04727         delta = 1;
04728 
04729     if (doRaw)
04730                 ret = pdv_wait_images_raw(pdv_p, delta);
04731         else
04732                 ret = pdv_wait_images(pdv_p, delta);
04733 
04734     edt_get_timestamp(pdv_p, timep, pdv_p->donecount - 1);
04735     return (ret);
04736 }
04737 
04753 unsigned char *
04754 pdv_wait_last_image_timed(PdvDev * pdv_p, u_int * timep)
04755 {
04756     return pdv_wait_last_image_timed_raw(pdv_p, timep, FALSE);
04757 }
04758  
04763 unsigned char *
04764 pdv_last_image_timed(PdvDev * pdv_p, u_int * timep)
04765 {
04766  
04767     return pdv_last_image_timed_raw(pdv_p, timep, FALSE);
04768 }
04769 
04790 unsigned char *
04791 pdv_wait_last_image_raw(PdvDev * pdv_p, int *nSkipped, int doRaw)
04792 {
04793     u_char *ret;
04794     int     donecount;
04795     int     last_wait;
04796     int     delta;
04797 
04798     donecount = edt_done_count(pdv_p);
04799     last_wait = pdv_p->donecount;
04800 
04801     edt_msg(DBG2, "pdv_wait_last_image() last %d cur %d\n",
04802             last_wait, donecount);
04803 
04804     delta = donecount - last_wait;
04805 
04806     if (nSkipped)
04807         *nSkipped = (delta) ? delta - 1 : 0;
04808 
04809     if (delta == 0)
04810         delta = 1;
04811 
04812     if (doRaw)
04813                 ret = pdv_wait_images_raw(pdv_p, delta);
04814         else
04815                 ret = pdv_wait_images(pdv_p, delta);
04816 
04817     return (ret);
04818 }
04819 
04843 unsigned char *
04844 pdv_wait_last_image(PdvDev * pdv_p, int *nSkipped)
04845 {
04846         return pdv_wait_last_image_raw(pdv_p, nSkipped, FALSE);
04847 }
04848 
04867 unsigned char *
04868 pdv_wait_next_image_raw(PdvDev * pdv_p, int *nSkipped, int doRaw)
04869 {
04870     u_char *ret;
04871     int     donecount;
04872     int     last_wait;
04873     int     delta;
04874 
04875     donecount = edt_done_count(pdv_p);
04876     last_wait = pdv_p->donecount;
04877 
04878     edt_msg(DBG2, "pdv_wait_last_image() last %d cur %d\n",
04879             last_wait, donecount);
04880 
04881     delta = donecount - last_wait;
04882 
04883     if (*nSkipped)
04884         *nSkipped = (delta) ? delta - 1 : 0;
04885 
04886 
04887     if (delta == 0)
04888         delta = 1;
04889 
04890     delta++;
04891 
04892     if (doRaw)
04893                 ret = pdv_wait_images_raw(pdv_p, delta);
04894         else
04895             ret = pdv_wait_images(pdv_p, delta);
04896 
04897     return (ret);
04898 }
04899 
04909 unsigned char *
04910 pdv_wait_next_image(PdvDev * pdv_p, int *nSkipped)
04911 {
04912  
04913     return pdv_wait_next_image_raw(pdv_p, nSkipped, FALSE);
04914 }
04915 
04916 
04926 int
04927 pdv_in_continuous(PdvDev * pdv_p)
04928 {
04929     edt_msg(DBG2, "pdv_in_continuous() %x\n",
04930             pdv_p->dd_p->continuous);
04931     return pdv_p->dd_p->continuous;
04932 }
04933  /* end acquisition */
04935 
04936 void
04937 pdv_check(PdvDev * pdv_p)
04938 {
04939     int     stat;
04940     int     overrun;
04941 
04942     stat = edt_reg_read(pdv_p, PDV_STAT);
04943     overrun = edt_ring_buffer_overrun(pdv_p);
04944     edt_msg(DBG2, "pdv_check() stat %x overrun %x\n",
04945             stat, overrun);
04946     if ((stat & PDV_OVERRUN) || overrun)
04947     {
04948         if (pdv_p->dd_p->continuous)
04949             pdv_stop_hardware_continuous(pdv_p);
04950 
04951         pdv_flush_fifo(pdv_p);
04952 
04953         pdv_multibuf(pdv_p, pdv_p->ring_buffer_numbufs);
04954 
04955         if (pdv_p->dd_p->continuous)
04956             pdv_start_hardware_continuous(pdv_p);
04957     }
04958 }
04959 
04960 void
04961 pdv_checkfrm(PdvDev * pdv_p, u_short * imagebuf, u_int imagesize, int verbose)
04962 {
04963     u_short *tmpp;
04964 
04965     for (tmpp = (u_short *) imagebuf;
04966          tmpp < (u_short *) (&imagebuf[imagesize]); tmpp++)
04967     {
04968         if (*tmpp & 0xf000)
04969         {
04970             edt_msg(DBG2, "found start of image %x at %x %d\n",
04971                     *tmpp >> 12,
04972                     tmpp - (u_short *) imagebuf,
04973                     tmpp - (u_short *) imagebuf);
04974             if (tmpp != imagebuf)
04975             {
04976                 int     curdone;
04977                 int     curtodo;
04978 
04979                 edt_reg_write(pdv_p, PDV_CMD, PDV_RESET_INTFC);
04980                 pdv_flush_fifo(pdv_p);
04981                 curdone = edt_done_count(pdv_p);
04982                 curtodo = edt_get_todo(pdv_p);
04983                 edt_msg(DBG2, "done %d todo %d\n", curdone, curtodo);
04984                 {
04985                     pdv_stop_continuous(pdv_p);
04986                     edt_set_buffer(pdv_p, curdone);
04987                     pdv_setup_continuous(pdv_p);
04988                     pdv_start_images(pdv_p, pdv_p->ring_buffer_numbufs -
04989                                      (curtodo - curdone));
04990                 }
04991             }
04992             break;
04993         }
04994     }
04995 }
04996 
04997 u_char *
04998 pdv_get_interleave_data(PdvDev *pdv_p, u_char *buf)
04999 
05000 {
05001         if (!pdv_process_inplace(pdv_p))
05002         {
05003                 return  buf + pdv_get_dmasize(pdv_p);
05004         }
05005         else
05006                 return buf;
05007 }
05008 
05009 
05036 unsigned char *
05037 pdv_wait_images_raw(PdvDev * pdv_p, int count)
05038 {
05039     u_char *buf;
05040     Dependent *dd_p;
05041     static int last_timeout = 0;
05042 
05043     edt_msg(DBG2, "pdv_wait_images_raw(%d)\n", count);
05044 
05045     if (pdv_p == NULL || pdv_p->dd_p == NULL)
05046                 return NULL;
05047 
05048     dd_p = pdv_p->dd_p;
05049 
05050     if (pdv_specinst_serial_triggered(pdv_p))
05051                 pdv_posttrigger_specinst(pdv_p);
05052 
05053     if (pdv_p->devid == DMY_ID)
05054     {
05055                 u_char *buf;
05056                 u_int  *tmpp;
05057 
05058                 buf = edt_next_writebuf(pdv_p);
05059                 tmpp = (u_int *) buf;
05060                 if (*tmpp != 0xaabbccdd)
05061                 {
05062                         pdv_dmy_data(buf, dd_p->width, dd_p->height, dd_p->depth);
05063                 }
05064                 *tmpp = 0xaabbccdd;
05065                 dd_p->last_image = buf;
05066                 dd_p->last_raw = buf;
05067     if (dd_p->markras)
05068         pdv_mark_ras(buf, dd_p->rascnt, dd_p->width, dd_p->height,
05069                      dd_p->markrasx, dd_p->markrasy);
05070     if (dd_p->markbin)
05071         pdv_mark_bin(buf, dd_p->rascnt, dd_p->width, dd_p->height, 4, 0);
05072 
05073     if (dd_p->markbin || dd_p->markras) dd_p->rascnt++ ;
05074                 return (buf);
05075     }
05076 
05077 
05078     last_timeout = edt_timeouts(pdv_p);
05079     buf = edt_wait_for_buffers(pdv_p, count);
05080 
05081         return buf;
05082 
05083  
05084 }
05085 
05086 
05132 u_char *
05133 pdv_wait_images(PdvDev *pdv_p, int count)
05134 
05135 {
05136    u_char *buf;
05137     u_char *retval;
05138     Dependent *dd_p;
05139 
05140     edt_msg(DBG2, "pdv_wait_images(%d)\n", count);
05141 
05142     if (pdv_p == NULL || pdv_p->dd_p == NULL)
05143                 return NULL;
05144 
05145     dd_p = pdv_p->dd_p;
05146 
05147     if (dd_p->swinterlace)
05148     {
05149                 pdv_alloc_tmpbuf(pdv_p);        
05150     }
05151    
05152         buf = pdv_wait_images_raw(pdv_p, count);
05153 
05154         if (dd_p->swinterlace)
05155         {
05156                 
05157                 if (!pdv_process_inplace(pdv_p))
05158                 {
05159                         retval = buf + pdv_get_dmasize(pdv_p);
05160                 }
05161                 else
05162                         retval = buf;
05163 
05164                 pdv_deinterlace(pdv_p, dd_p, buf, retval);
05165 
05166                 dd_p->last_raw = buf;
05167                 dd_p->last_image = retval;
05168         }
05169     else
05170     {
05171                 retval = buf;
05172                 dd_p->last_raw = buf;
05173                 dd_p->last_image = buf;
05174         }
05175 
05176 /* problem is that pdv_flshow calling images_raw directly - talk to steve */
05177     if (pdv_p->devid != DMY_ID)
05178         {
05179     if (dd_p->markras)
05180         pdv_mark_ras(buf, dd_p->rascnt, dd_p->width, dd_p->height,
05181                      dd_p->markrasx, dd_p->markrasy);
05182     if (dd_p->markbin)
05183         pdv_mark_bin(buf, dd_p->rascnt, dd_p->width, dd_p->height, 4, 0);
05184 
05185     if (dd_p->markbin || dd_p->markras) dd_p->rascnt++ ;
05186         }
05187 
05188 
05189     return (retval);
05190 }
05191 
05192 int
05193 pdv_slop(PdvDev * pdv_p)
05194 {
05195     return (pdv_p->dd_p->slop);
05196 }
05197 
05198 
05199 int
05200 pdv_set_slop(PdvDev * pdv_p, int slop)
05201 {
05202     edt_msg(DBG2, "pdv_set_slop()\n");
05203 
05204     pdv_p->dd_p->slop = slop;
05205     return (0);
05206 }
05207 
05208 
05225 int
05226 pdv_get_header_size(PdvDev * pdv_p)
05227 {
05228     return (pdv_p->dd_p->header_size);
05229 }
05230 
05253 int
05254 pdv_get_header_position(PdvDev * pdv_p)
05255 {
05256     return (pdv_p->dd_p->header_position);
05257 }
05258 
05275 int
05276 pdv_get_header_offset(PdvDev * pdv_p)
05277 {
05278     switch (pdv_p->dd_p->header_position)
05279     {
05280         case PDV_HEADER_BEFORE:
05281         pdv_p->dd_p->header_offset = 0;
05282         break;
05283     case PDV_HEADER_AFTER:
05284         pdv_p->dd_p->header_offset = pdv_p->dd_p->imagesize;
05285         break;
05286 
05287     }
05288 
05289     return (pdv_p->dd_p->header_offset);
05290 }
05291 
05300 int
05301 pdv_get_header_dma(PdvDev * pdv_p)
05302 {
05303     return (pdv_p->dd_p->header_dma);
05304 }
05305 
05315 int
05316 pdv_extra_headersize(PdvDev * pdv_p)
05317 
05318 {
05319     if (pdv_p->dd_p->header_size && (!pdv_p->dd_p->header_dma) &&
05320         (pdv_p->dd_p->header_position != PDV_HEADER_WITHIN))
05321         return pdv_p->dd_p->header_size;
05322 
05323     return 0;
05324 }
05325 
05335 void
05336 pdv_set_header_size(PdvDev * pdv_p, int header_size)
05337 {
05338     edt_msg(DBG2, "pdv_set_header_size()\n");
05339 
05340     pdv_p->dd_p->header_size = header_size;
05341 
05342 }
05343 
05355 void
05356 pdv_set_header_position(PdvDev * pdv_p, int header_position)
05357 
05358 {
05359     edt_msg(DBG2, "pdv_set_header_position(%d)\n", header_position);
05360 
05361     pdv_p->dd_p->header_position = header_position;
05362 }
05363 
05373 void
05374 pdv_set_header_dma(PdvDev * pdv_p, int header_dma)
05375 {
05376     edt_msg(DBG2, "pdv_set_header_dma(%d,%d)\n", header_dma);
05377 
05378     pdv_p->dd_p->header_dma = header_dma;
05379 }
05380 
05381 
05388 void
05389 pdv_set_header_offset(PdvDev * pdv_p, int header_offset)
05390 
05391 {
05392     edt_msg(DBG2, "pdv_set_header_offset(%d,%d)\n", header_offset);
05393 
05394     pdv_p->dd_p->header_offset = header_offset;
05395 }
05396  /* end settings */
05398 
05423 int
05424 pdv_shutter_method(PdvDev * pdv_p)
05425 {
05426     edt_msg(DBG2, "pdv_shutter_method()\n");
05427 
05428     return pdv_p->dd_p->camera_shutter_timing;
05429 }
05430 
05438 void
05439 pdv_set_interlace(PdvDev * pdv_p, int interlace)
05440 {
05441     edt_msg(DBG2, "pdv_set_interlace()\n");
05442 
05443     pdv_p->dd_p->swinterlace = interlace;
05444 
05445     pdv_setup_postproc(pdv_p, pdv_p->dd_p, NULL);
05446 
05447 }
05448 
05506 pdv_interlace_method(PdvDev * pdv_p)
05507 {
05508     edt_msg(DBG2, "pdv_interlace_method()\n");
05509 
05510     return pdv_p->dd_p->swinterlace;
05511 }
05512 
05513 
05530 int
05531 pdv_debug(int flag)
05532 {
05533     int     oldval = Pdv_debug;
05534 
05535     edt_msg(DBG2, "pdv_debug()\n");
05536 
05537     Pdv_debug = flag;
05538     return (oldval);
05539 }
05540 
05549 int
05550 pdv_debug_level()
05551 {
05552     return Pdv_debug;
05553 }
05554 
05555 
05567 int
05568 pdv_overrun(PdvDev * pdv_p)
05569 {
05570     int     overrun;
05571 
05572     edt_msg(DBG2, "pdv_overrun()\n");
05573 
05574     if (pdv_p->devid == DMY_ID)
05575         return (0);
05576     edt_ioctl(pdv_p, EDTG_OVERFLOW, &overrun);
05577     return (overrun);
05578 }
05579 
05598 int
05599 pdv_serial_wait(PdvDev * pdv_p, int msecs, int count)
05600 {
05601     edt_buf tmp;
05602     int     ret;
05603 
05604     if (msecs == 0)
05605         msecs = pdv_p->dd_p->serial_timeout;
05606 
05607     tmp.desc = msecs;
05608     tmp.value = count;
05609     edt_ioctl(pdv_p, EDTS_SERIALWAIT, &tmp);
05610     ret = (int) tmp.value;
05611     edt_msg(DBG2, "pdv_serial_wait(%d, %d) %d\n", msecs, count, ret);
05612     return (ret);
05613 }
05614 
05628 int
05629 pdv_serial_wait_next(EdtDev * pdv_p, int msecs, int count)
05630 {
05631     int     ret;
05632     int     newcount = count;
05633 
05634     if (pdv_p->devid == PDVFOI_ID)
05635     {
05636         if (newcount)
05637             newcount += 2;
05638         ret = pdv_serial_wait(pdv_p, msecs, newcount);
05639         if (ret >= 2)
05640             ret -= 2;
05641     }
05642     else
05643         ret = pdv_serial_wait(pdv_p, msecs, count);
05644     return (ret);
05645 }
05646 
05664 int
05665 pdv_set_waitchar(PdvDev * pdv_p, int enable, u_char wchar)
05666 {
05667     edt_buf tmp;
05668     int     ret;
05669 
05670 
05671     tmp.desc = enable;
05672     tmp.value = wchar;
05673     ret = edt_ioctl(pdv_p, EDTS_WAITCHAR, &tmp);
05674     pdv_p->dd_p->serial_waitc = wchar;
05675     if (!enable) /* top bit is flag for disabled (internally) */
05676         pdv_p->dd_p->serial_waitc |= 0x100;
05677     edt_msg(DBG2, "pdv_set_waitchar(%d, %02x) returns %d\n", enable, wchar, ret);
05678     return (ret);
05679 }
05680 
05693 int
05694 pdv_get_waitchar(PdvDev * pdv_p, u_char *waitc)
05695 {
05696     int ret;
05697 
05698     if (pdv_p->dd_p->serial_waitc & 0x100)
05699     {
05700         *waitc = pdv_p->dd_p->serial_waitc & 0xff;
05701         ret = 0;
05702     }
05703     else
05704     {
05705         *waitc = pdv_p->dd_p->serial_waitc;
05706         ret = 1;
05707     }
05708     return ret;
05709 }
05710 
05711 
05712 int
05713 pdv_get_fulldma_size(PdvDev *pdv_p, int *extrasizep)
05714 
05715 {
05716    int     size = pdv_get_imagesize(pdv_p);
05717 
05718     int     slop = pdv_slop(pdv_p);
05719     int     extrasize;
05720     Dependent *dd_p = pdv_p->dd_p;
05721 
05722     int     header_before = (pdv_p->dd_p->header_position == PDV_HEADER_BEFORE);
05723 
05724 
05725     extrasize = slop + pdv_extra_headersize(pdv_p);
05726 
05727     if (dd_p->swinterlace || size != pdv_get_dmasize(pdv_p))
05728     {
05729         /* If extra buffer needed, put it after the data */
05730 
05731         if (!pdv_process_inplace(pdv_p) || size != pdv_get_dmasize(pdv_p))
05732         {
05733             int     newsize = pdv_get_dmasize(pdv_p);
05734                 
05735             extrasize += size;  /* use second part of buffer for interlace
05736                                  * result */
05737 
05738             size = newsize;
05739         }
05740     }
05741 
05742     if (extrasizep)
05743         *extrasizep = extrasize;
05744 
05745     return size;
05746 }
05747 
05748 int
05749 pdv_total_block_size(PdvDev *pdv_p, int numbufs)
05750 
05751 {
05752         int extrasize = 0;
05753         int size;
05754 
05755         size = pdv_get_fulldma_size(pdv_p, &extrasize);
05756 
05757     /* round up */
05758     size = edt_get_total_bufsize(pdv_p, size,extrasize) * numbufs;
05759 
05760         return size;
05761         
05762 }
05763 
05764 int
05765 pdv_multibuf_block(PdvDev *pdv_p, int numbufs, u_char *block, int blocksize)
05766 
05767 {
05768     int size;
05769 
05770     int extrasize;
05771 
05772     int ret;
05773     int     header_before = (pdv_p->dd_p->header_position == PDV_HEADER_BEFORE);
05774 
05775     size = pdv_get_fulldma_size(pdv_p, &extrasize);
05776 
05777     pdv_setup_dma(pdv_p);
05778 
05779     ret = edt_configure_block_buffers_mem(pdv_p, 
05780                                           size, 
05781                                           numbufs, 
05782                                           EDT_READ, 
05783                                           extrasize, 
05784                                           header_before,
05785                                           block) ;
05786 
05787 
05788     return ret;
05789 
05790 }
05791 
05792 int
05793 pdv_multibuf_separate(PdvDev *pdv_p, int numbufs, u_char **buffers)
05794 
05795 {
05796     int     size = pdv_get_imagesize(pdv_p);
05797     int ret;
05798 
05799     Dependent *dd_p = pdv_p->dd_p;
05800 
05801     if (dd_p->swinterlace || size != pdv_get_dmasize(pdv_p))
05802     {
05803         /* If extra buffer needed, put it after the data */
05804 
05805         if (!pdv_process_inplace(pdv_p) || size != pdv_get_dmasize(pdv_p))
05806         {
05807             edt_msg_perror(PDVFATAL,"Interlace not inplace fails for multibuf_separate\n");
05808             return -1;
05809         }
05810     }
05811 
05812     size = pdv_get_fulldma_size(pdv_p, NULL);
05813 
05814     pdv_setup_dma(pdv_p);
05815 
05816     ret = edt_configure_ring_buffers(pdv_p, size, numbufs, EDT_READ, buffers) ;
05817 
05818     return ret;
05819    
05820 }
05821 
05844 int
05845 pdv_multibuf(PdvDev * pdv_p, int numbufs)
05846 {
05847         /* set number of buffers, library allocated. */
05848 
05849 /* define if not enough memory for contiguous allocation */
05850 /* but beware of interlace since currently not supported in separate */
05851 /* #ifdef RADSTONE*/
05852 #if defined(XCALIBURCOMMON) || defined(VMIC)
05853     return pdv_multibuf_separate(pdv_p, numbufs,NULL);
05854 #else
05855     return pdv_multibuf_block(pdv_p, numbufs, NULL, 0);
05856 #endif
05857 
05858 }
05859 
05893 int
05894 pdv_set_buffers(PdvDev * pdv_p, int numbufs, unsigned char **bufarray)
05895 {
05896         /* set number of buffers, user allocated. */
05897     int     size = pdv_get_dmasize(pdv_p);
05898 
05899     edt_msg(DBG2, "pdv_set_buffers(%d %x) (size %d)\n", numbufs, bufarray, size);
05900 
05901     pdv_setup_dma(pdv_p);
05902 
05903     return (edt_configure_ring_buffers(pdv_p, size, numbufs, EDT_READ, bufarray));
05904 }
05905 
05906 /* plus size - so far just used for merge */
05907 int
05908 pdv_set_buffers_x(PdvDev * pdv_p, int numbufs, int size, unsigned char **bufs)
05909 {
05910 
05911     edt_msg(DBG2, "pdv_set_buffers(%d %x) (size %d)\n", numbufs, bufs, size);
05912 
05913     pdv_setup_dma(pdv_p);
05914 
05915     return (edt_configure_ring_buffers(pdv_p, size, numbufs, EDT_READ, bufs));
05916 }
05917 
05918 
05933 int
05934 pdv_image_size(PdvDev * pdv_p)
05935 {
05936     int     size;
05937 
05938     size = pdv_p->dd_p->imagesize;
05939 
05940     if (pdv_p->dd_p->slop)
05941     {
05942 
05943         edt_msg(DBG2, "pdv_image_size: adjusting size %x by slop %x to %x\n",
05944                 size, pdv_p->dd_p->slop, size - pdv_p->dd_p->slop);
05945 
05946         size -= pdv_p->dd_p->slop;
05947 
05948     }
05949 
05950     if (pdv_p->dd_p->header_dma)
05951                 size += pdv_p->dd_p->header_size;
05952 
05953     edt_msg(DBG2, "pdv_image_size() %d\n", size);
05954 
05955     return size;
05956 
05957 }
05958 
05959 
05973 u_char *
05974 pdv_get_last_image(PdvDev * pdv_p)
05975 {
05976     edt_msg(DBG2, "pdv_get_last_image()\n");
05977 
05978     return (pdv_p->dd_p->last_image);
05979 }
05980 
05995 u_char *
05996 pdv_get_last_raw(PdvDev * pdv_p)
05997 {
05998     edt_msg(DBG2, "pdv_get_last_raw()\n");
05999 
06000     return (pdv_p->dd_p->last_raw);
06001 }
06002 
06015 u_char **
06016 pdv_buffer_addresses(PdvDev * pdv_p)
06017 {
06018         /* (same as edt_buffer_addresses) */
06019     return (pdv_p->ring_buffers);
06020 }
06021 
06047 void
06048 pdv_start_hardware_continuous(PdvDev * pdv_p /* , int frames */ )
06049 {
06050     int     data_path;
06051 
06052     /* data_path = edt_reg_read(pdv_p, PDV_DATA_PATH); */
06053     data_path = pdv_p->dd_p->datapath_reg & ~PDV_CONTINUOUS;
06054     /* data_path = 0x5 ; */
06055     edt_msg(DBG2, "pdv_start_hardware_continuous()\n");
06056 
06057     if (pdv_p->devid == PDVFOI_ID)
06058     {
06059         char    tmpbuf[10];
06060         int     ret;
06061 
06062         ret = pdv_serial_wait(pdv_p, 100, 0);
06063         if (ret > 10)
06064             pdv_reset_serial(pdv_p);
06065         else
06066             pdv_serial_read(pdv_p, tmpbuf, ret);
06067 
06068     }
06069     /* clear first - let driver set */
06070     if (pdv_p->devid == PDVFOI_ID)
06071     {
06072         char    tmpbuf[10];
06073         int     ret;
06074 
06075         ret = pdv_serial_wait(pdv_p, 100, 0);
06076         if (ret > 10)
06077             pdv_reset_serial(pdv_p);
06078         else
06079             pdv_serial_read(pdv_p, tmpbuf, ret);
06080 
06081    }
06082     edt_reg_write(pdv_p, PDV_DATA_PATH, data_path | PDV_CONTINUOUS);
06083     pdv_p->dd_p->datapath_reg = data_path;
06084 }
06085 
06086 
06096 void
06097 pdv_stop_hardware_continuous(PdvDev * pdv_p)
06098 {
06099     int     data_path;
06100 
06101     /* data_path = edt_reg_read(pdv_p, PDV_DATA_PATH); */
06102     data_path = pdv_p->dd_p->datapath_reg;
06103     edt_msg(DBG2, "pdv_stop_hardware_continuous()\n");
06104     data_path &= ~PDV_CONTINUOUS;
06105     edt_reg_write(pdv_p, PDV_DATA_PATH, data_path);
06106     pdv_p->dd_p->datapath_reg = data_path;
06107 
06108     if (pdv_p->devid == PDVFOI_ID)
06109     {
06110         edt_reg_write(pdv_p,FOI_WR_MSG_STAT, FOI_FIFO_FLUSH);
06111     }
06112 
06113 }
06114 
06125 int
06126 pdv_set_serial_parity(PdvDev * pdv_p, char parity)
06127 {
06128     if (pdv_p->devid == PDVAERO_ID)
06129     {
06130         int val = 0;
06131         switch(parity)
06132         {
06133 
06134         case 'e':
06135                 val = 1;
06136         break;
06137         case 'o':
06138                 val = 3;
06139         break;
06140         case 'n':
06141                 val = 0;
06142         break;
06143         default:
06144                 edt_msg(DBG1, "parity must be e, o, or n");
06145                 return -1;
06146         }
06147 
06148         edt_reg_write(pdv_p,PDV_SERIAL_PARITY,val);
06149         return 0;
06150     }
06151     else
06152     {
06153         edt_msg(DBG1,"parity not an option for this board");
06154     }
06155     return -1;
06156 }
06157 
06173 pdv_set_baud(PdvDev * pdv_p, int baud)
06174 {
06175     Dependent *dd_p = pdv_p->dd_p;
06176     u_int   baudbits = 0;
06177     int     id=pdv_p->devid;
06178     u_int   new, baudreg;
06179     u_int   cntl;
06180     int     donew        = 0;
06181     int     ret = 0;
06182 
06183     if (dd_p->xilinx_rev < 2 || dd_p->xilinx_rev > 32)
06184     {
06185         edt_msg(DBG2, "pdv_set_baud() warning: can't enable, N/A this xilinx (%x)\n",
06186                 pdv_p->dd_p->xilinx_rev);
06187         return -1;
06188     }
06189 
06190     if (edt_is_dvcl(pdv_p) || edt_is_dvfox(pdv_p) || (id == PDVA_ID))
06191         donew = 1;
06192 
06193     switch (baud)
06194     {
06195         case 9600:
06196             baudbits = 0;
06197             baudreg = 0x80;
06198             break;
06199 
06200         case 19200:
06201             baudbits = PDV_BAUD0;
06202             baudreg = 0x3f;
06203             break;
06204 
06205         case 38400:
06206             baudbits = PDV_BAUD1;
06207             baudreg = 0x1f;
06208             break;
06209 
06210         case 115200:
06211             baudbits = PDV_BAUD0 | PDV_BAUD1;
06212             baudreg = 0x09;
06213             break;
06214 
06215         case 57600:
06216             baudbits = PDV_BAUD0 | PDV_BAUD1;   /* ALERT (funky old DV or DVK only) */
06217             donew = 1;
06218             baudreg = 0x014;
06219             break;
06220 
06221         default:
06222             donew = 1;
06223             baudreg = (unsigned int)(((20000000.0 / (16.0 * (double)baud)) - 2.0) + 0.5) ; 
06224             edt_msg(DBG2, "pdv_set_baud(%d) using new method, reg %02x\n", baud, baudreg);
06225             break;
06226     }
06227 
06228     if (donew && (!dd_p->register_wrap))
06229     {
06230         if (baudreg > 0xff)
06231         {
06232             edt_msg(DBG2, "pdv_set_baud(%d) (baudreg %x) BAD VALUE not set\n", baud, baudreg);
06233             ret = -1; 
06234         }
06235         else 
06236         {
06237             edt_msg(DBG2, "pdv_set_baud(%d) (baudreg %x) using NEW baud reg\n", baud, baudreg);
06238             edt_reg_write(pdv_p, PDV_BRATE, baudreg);
06239             new = edt_reg_read(pdv_p, PDV_BRATE);
06240             if (new != baudreg)
06241             {
06242                 edt_msg(DBG2, "pdv_set_baud(%d) (baudreg %x) readback ERROR\n", baud, baudreg);
06243                 ret = -1;
06244             }
06245         }
06246     }
06247 
06248     else /* old way */
06249     {
06250         edt_msg(DBG2, "pdv_set_baud(%d) (baudbits %x) using OLD baud bits\n", baud, baudbits);
06251         cntl = edt_reg_read(pdv_p, PDV_SERIAL_DATA_CNTL);
06252         cntl &= ~PDV_BAUD_MASK;
06253         cntl |= baudbits;
06254         edt_reg_write(pdv_p, PDV_SERIAL_DATA_CNTL, cntl);
06255     }
06256 
06257     return ret;
06258 }
06259 
06268 int
06269 pdv_get_baud(PdvDev * pdv_p)
06270 {
06271     u_int   baudbits;
06272     int     ret = 0;
06273 
06274     if (pdv_p->dd_p->xilinx_rev < 2 || pdv_p->dd_p->xilinx_rev > 32)
06275     {
06276         edt_msg(DBG2, "pdv_set_baud() WARNING: can't enable, N/A this xilinx (%x)\n",
06277                 pdv_p->dd_p->xilinx_rev);
06278         return -1;
06279     }
06280 
06281     baudbits = edt_reg_read(pdv_p, PDV_SERIAL_DATA_CNTL) & PDV_BAUD_MASK;
06282 
06283     switch (baudbits)
06284     {
06285     case 0:
06286         return 9600;
06287 
06288     case PDV_BAUD0:
06289         return 19200;
06290 
06291     case PDV_BAUD1:
06292         return 38400;
06293 
06294     case PDV_BAUD0 | PDV_BAUD1:
06295         return 115200;
06296 
06297     default:
06298         edt_msg(DBG2, "ERROR: pdv_get_baud(%d) -- invalid bits???\n", baudbits);
06299         return 0;
06300     }
06301 }
06302 
06318 void
06319 pdv_perror(char *err)
06320 {
06321     edt_perror(err);
06322 }
06323 
06324 void
06325 pdv_setdebug(PdvDev * pdv_p, int debug)
06326 {
06327     Pdv_debug = debug;
06328 }
06329 
06330 
06331 
06332 
06333 
06346 void
06347 pdv_reset_serial(PdvDev * pdv_p)
06348 {
06349     edt_reset_serial(pdv_p);
06350 }
06351 
06352 
06373 uchar_t *
06374 pdv_alloc(int size)
06375 {
06376     return edt_alloc(size);
06377 }
06378 
06379 
06386 void
06387 pdv_free(uchar_t * ptr)
06388 {
06389     edt_free(ptr);
06390 }
06391 
06392 
06393 
06394 static u_short zero[] = {
06395     0x0F80,
06396     0x3FE0,
06397     0x38E0,
06398     0x7070,
06399     0x6030,
06400     0xE038,
06401     0xE038,
06402     0xE038,
06403     0xE038,
06404     0xE038,
06405     0xE038,
06406     0xE038,
06407     0x6030,
06408     0x7070,
06409     0x38E0,
06410     0x3FE0,
06411     0x0F80,
06412 };
06413 static u_short one[] = {
06414     0xFC00,
06415     0xFC00,
06416     0x1C00,
06417     0x1C00,
06418     0x1C00,
06419     0x1C00,
06420     0x1C00,
06421     0x1C00,
06422     0x1C00,
06423     0x1C00,
06424     0x1C00,
06425     0x1C00,
06426     0x1C00,
06427     0x1C00,
06428     0x1C00,
06429     0xFF80,
06430     0xFF80,
06431 };
06432 static u_short two[] = {
06433     0x7E00,
06434     0x7F80,
06435     0x4380,
06436     0x01C0,
06437     0x01C0,
06438     0x01C0,
06439     0x01C0,
06440     0x0380,
06441     0x0700,
06442     0x0E00,
06443     0x1C00,
06444     0x3800,
06445     0x3800,
06446     0x7000,
06447     0xE000,
06448     0xFFC0,
06449     0xFFC0,
06450 };
06451 static u_short three[] = {
06452     0x7E00,
06453     0xFF00,
06454     0x8780,
06455     0x0380,
06456     0x0380,
06457     0x0380,
06458     0x0F00,
06459     0x7C00,
06460     0x7E00,
06461     0x0F00,
06462     0x0380,
06463     0x0380,
06464     0x0380,
06465     0x0380,
06466     0x8700,
06467     0xFF00,
06468     0xFC00,
06469 };
06470 static u_short four[] = {
06471     0x0380,
06472     0x0780,
06473     0x0F80,
06474     0x0F80,
06475     0x1F80,
06476     0x1B80,
06477     0x3380,
06478     0x3380,
06479     0x6380,
06480     0xE380,
06481     0xFFE0,
06482     0xFFE0,
06483     0xFFE0,
06484     0x0380,
06485     0x0380,
06486     0x0380,
06487     0x0380,
06488 };
06489 static u_short five[] = {
06490     0xFF80,
06491     0xFF80,
06492     0xE000,
06493     0xE000,
06494     0xE000,
06495     0xC000,
06496     0xF800,
06497     0xFE00,
06498     0x0F00,
06499     0x0780,
06500     0x0380,
06501     0x0380,
06502     0x0380,
06503     0x0380,
06504     0x8700,
06505     0xFE00,
06506     0xFC00,
06507 };
06508 static u_short six[] = {
06509     0x07E0,
06510     0x1FE0,
06511     0x3C20,
06512     0x7000,
06513     0x7000,
06514     0xE000,
06515     0xE780,
06516     0xFFE0,
06517     0xF0E0,
06518     0xE070,
06519     0xE070,
06520     0xE070,
06521     0xE070,
06522     0x7070,
06523     0x70E0,
06524     0x3FC0,
06525     0x0F80,
06526 };
06527 static u_short seven[] = {
06528     0xFFC0,
06529     0xFFC0,
06530     0x01C0,
06531     0x0180,
06532     0x0380,
06533     0x0700,
06534     0x0700,
06535     0x0E00,
06536     0x0C00,
06537     0x1C00,
06538     0x1800,
06539     0x3800,
06540     0x3800,
06541     0x3000,
06542     0x7000,
06543     0x7000,
06544     0x7000,
06545 };
06546 static u_short eight[] = {
06547     0x0F80,
06548     0x3FC0,
06549     0x71E0,
06550     0x70E0,
06551     0x70E0,
06552     0x7DE0,
06553     0x3FC0,
06554     0x1F00,
06555     0x1FC0,
06556     0x7FE0,
06557     0xF1F0,
06558     0xE0F0,
06559     0xE070,
06560     0xE070,
06561     0xF0E0,
06562     0x7FE0,
06563     0x1F80,
06564 };
06565 static u_short nine[] = {
06566     0x1F00,
06567     0x3FC0,
06568     0x70E0,
06569     0xE0E0,
06570     0xE070,
06571     0xE070,
06572     0xE070,
06573     0xE070,
06574     0x70F0,
06575     0x7FF0,
06576     0x1E70,
06577     0x0070,
06578     0x00E0,
06579     0x00E0,
06580     0x43C0,
06581     0x7F80,
06582     0x7E00,
06583 };
06584 
06585 static u_short *digits[] = {
06586     zero,
06587     one,
06588     two,
06589     three,
06590     four,
06591     five,
06592     six,
06593     seven,
06594     eight,
06595     nine,
06596 };
06597 
06598 
06599 
06600 static void
06601 set_square(int sx, int sy, u_short * buf, u_char * addr, int stride)
06602 {
06603 /*
06604  * colors
06605  */
06606 #define FG      200
06607 #define BG      0
06608 
06609     /*
06610      * get offset to square
06611      */
06612     register u_char *svptr;
06613     register u_char *ptr;
06614     int     i;
06615     int     bit;
06616     u_short tmp;
06617     int     val;
06618 
06619     svptr = addr + (stride * sy) + (sx);
06620 
06621     for (i = 0; i < 17; i++)
06622     {
06623         ptr = svptr;
06624         tmp = *buf++;
06625         for (bit = 15; bit >= 0; bit--)
06626         {
06627             if (tmp & (1 << bit))
06628             {
06629                 val = FG;
06630             }
06631             else
06632             {
06633                 val = BG;
06634             }
06635             *ptr++ = val;
06636         }
06637         svptr += stride;
06638     }
06639 }
06640 
06641 
06642 void
06643 pdv_mark_ras(u_char * addr, int n, int width, int height, int x, int y)
06644 {
06645 #define GAP     16
06646     set_square(x, y, digits[n / 1000000], addr, width);
06647     n %= 1000000;
06648     set_square(x + GAP, y, digits[n / 100000], addr, width);
06649     n %= 100000;
06650     set_square(x + (GAP * 2), y, digits[n / 10000], addr, width);
06651     n %= 10000;
06652     set_square(x + (GAP * 3), y, digits[n / 1000], addr, width);
06653     n %= 1000;
06654     set_square(x + (GAP * 4), y, digits[n / 100], addr, width);
06655     n %= 100;
06656     set_square(x + (GAP * 5), y, digits[n / 10], addr, width);
06657     n %= 10;
06658     set_square(x + (GAP * 6), y, digits[n], addr, width);
06659 }
06660 
06661 void
06662 pdv_mark_bin(u_char * addr, int n, int width, int height, int x, int y)
06663 {
06664     u_int   val = n;
06665     u_char *svptr;
06666 
06667     svptr = (u_char *) addr + (width * y) + x;
06668     *svptr++ = (val >> 24) & 0xff;
06669     *svptr++ = (val >> 16) & 0xff;
06670     *svptr++ = (val >> 8) & 0xff;
06671     *svptr++ = val & 0xff;
06672 }
06673 
06691 int
06692 pdv_serial_command_hex(PdvDev * pdv_p, char *str, int length)
06693 {
06694     char    buf[2];
06695     char   *p = &str[2];
06696     u_int   lval;
06697 
06698     sscanf(p, "%x", &lval);
06699     buf[0] = (char) (lval & 0xff);
06700     edt_msg(DBG2, "pdv_serial_command_hex(%s),0x%x\n", str, (u_char) (buf[0]));
06701 
06702     return pdv_serial_binary_command(pdv_p, buf, 1);
06703 }
06704 
06740 int
06741 pdv_set_roi(PdvDev * pdv_p, int hskip, int hactv, int vskip, int vactv)
06742 {
06743     Dependent *dd_p = pdv_p->dd_p;
06744     int     cam_w, cam_h;       /* camera actual w/h */
06745 
06746     edt_msg(DBG2, "pdv_set_roi(hskip %d hactv %d vskip %d vactv %d)\n",
06747             hskip, hactv, vskip, vactv);
06748 
06749     /*
06750      * ALERT: check for ROI xilinx capabilities here -- 4005 doesn't do ROI
06751      */
06752     if (dd_p->xilinx_rev < 2 || dd_p->xilinx_rev > 32)
06753     {
06754         edt_msg(DBG2, "pdv_set_roi(): WARNING: can't enable, N/A this xilinx (%x)\n",
06755                 dd_p->xilinx_rev);
06756         return -1;
06757     }
06758 
06759     cam_w = pdv_get_cam_width(pdv_p);
06760     cam_h = pdv_get_cam_height(pdv_p);
06761 
06762     /* check width/height for out of range, unless camera link or FOI */
06763     if (!pdv_is_cameralink(pdv_p))
06764     {
06765         if ((cam_w && ((hskip + hactv) > cam_w)) || ((hskip + hactv) <= 0))
06766         {
06767             edt_msg(DBG2, "ROI: horiz. skip/actv out of range error\n");
06768             return -1;
06769         }
06770         if ((cam_h && ((vskip + vactv) > cam_h)) || ((vskip + vactv) <= 0))
06771         {
06772             edt_msg(DBG2, "ROI: vert. skip/actv out of range error\n");
06773             return -1;
06774         }
06775     }
06776 
06777     /* vert must be even if dual chan, and regs set to value/2  */
06778     if (pdv_is_cameralink(pdv_p))
06779     {
06780         /* negative htaps is used for 24-bit (ex) coming in
06781            as a single 8-bit stream */
06782 
06783         if (dd_p->htaps > 0)
06784         {
06785             hactv = (hactv / dd_p->htaps) * dd_p->htaps;
06786             hskip = (hskip / dd_p->htaps) * dd_p->htaps;
06787         }
06788         vactv = (vactv / dd_p->vtaps) * dd_p->vtaps;
06789         vskip = (vskip / dd_p->vtaps) * dd_p->vtaps;
06790 
06791         
06792         if (dd_p->htaps > 0)
06793         {
06794             
06795             edt_reg_write(pdv_p, PDV_HSKIP, (hskip / dd_p->htaps));
06796             edt_reg_write(pdv_p, PDV_HACTV, (hactv / dd_p->htaps) - 1);
06797         }
06798         else
06799         {
06800             edt_reg_write(pdv_p, PDV_HSKIP, (hskip * -dd_p->htaps));
06801             edt_reg_write(pdv_p, PDV_HACTV, (hactv * -dd_p->htaps) - 1);
06802         }
06803 
06804         edt_reg_write(pdv_p, PDV_VSKIP, (vskip / dd_p->vtaps));
06805         edt_reg_write(pdv_p, PDV_VACTV, (vactv / dd_p->vtaps) - 1);
06806     }
06807     else if (dd_p->dual_channel)
06808     {
06809         vactv = (vactv / 2) * 2;
06810         vskip = (vskip / 2) * 2;
06811         edt_reg_write(pdv_p, PDV_VSKIP, (vskip / 2));
06812         edt_reg_write(pdv_p, PDV_HSKIP, hskip);
06813         edt_reg_write(pdv_p, PDV_VACTV, (vactv / 2) - 1);
06814         edt_reg_write(pdv_p, PDV_HACTV, hactv - 1);
06815     }
06816     else
06817     {
06818         edt_reg_write(pdv_p, PDV_HSKIP, hskip);
06819         edt_reg_write(pdv_p, PDV_VSKIP, vskip);
06820         edt_reg_write(pdv_p, PDV_HACTV, hactv - 1);
06821         edt_reg_write(pdv_p, PDV_VACTV, vactv - 1);
06822     }
06823 
06824     dd_p->hactv = hactv;
06825     dd_p->hskip = hskip;
06826     dd_p->vactv = vactv;
06827     dd_p->vskip = vskip;
06828 
06829     if (dd_p->roi_enabled)
06830         pdv_setsize(pdv_p, dd_p->hactv, dd_p->vactv);
06831 
06832     edt_set_dependent(pdv_p, dd_p);
06833 
06834     return 0;                   /* ALERT: need to return error from above if
06835                                  * any */
06836 }
06837 
06838 
06839 void
06840 pdv_cl_set_base_channels(PdvDev *pdv_p, int htaps, int vtaps)
06841 
06842 {
06843     Dependent *dd_p = pdv_p->dd_p;
06844      int taps = (htaps > vtaps)? htaps : vtaps;
06845 
06846     dd_p->cl_data_path = (taps - 1) << 4 | (dd_p->depth - 1);
06847 
06848     dd_p->htaps = htaps;
06849     dd_p->vtaps = vtaps;
06850 
06851     edt_reg_write(pdv_p, PDV_CL_DATA_PATH, dd_p->cl_data_path);
06852 
06853     edt_set_dependent(pdv_p, dd_p);
06854 
06855     pdv_set_roi(pdv_p, dd_p->hskip, dd_p->hactv, dd_p->vskip, dd_p->vactv);
06856 }
06857 
06858 
06859 
06860 /*****************************************************/
06861 /* Set the Dalsa line scan using AIAG - hskip and hactv */
06862 /* control the exposure time and the linerate */
06863 /*****************************************************/
06864 
06865 int
06866 pdv_dalsa_ls_set_expose(PdvDev * pdv_p, int hskip, int hactv)
06867 {
06868     Dependent *dd_p = pdv_p->dd_p;
06869 
06870     edt_msg(DBG2, "pdv_dalsa_ls_set_expose(hskip %d hactv %d)\n", hskip, hactv);
06871 
06872     /*
06873      * ALERT: check for ROI xilinx capabilities here -- 4005 doesn't do ROI
06874      */
06875     if (dd_p->xilinx_rev < 2 || dd_p->xilinx_rev > 32)
06876     {
06877         edt_msg(DBG2, "pdv_dalsa_ls_set_expose(): WARNING: can't enable, N/A this xilinx (%x)\n", dd_p->xilinx_rev);
06878         return -1;
06879     }
06880 
06881     edt_reg_write(pdv_p, PDV_HSKIP, hskip);
06882     edt_reg_write(pdv_p, PDV_HACTV, hactv - 1);
06883 
06884     dd_p->hactv = hactv;
06885     dd_p->hskip = hskip;
06886 
06887     edt_set_dependent(pdv_p, dd_p);
06888     pdv_enable_roi(pdv_p, 1);
06889 
06890     return 0;                   /* ALERT: need to return error from above if *
06891                                  * any */
06892 }
06893 
06894 
06903 int
06904 pdv_auto_set_roi(PdvDev * pdv_p)
06905 {
06906     int     w = pdv_p->dd_p->width;
06907     int     h = pdv_p->dd_p->height;
06908     int     ret;
06909 
06910     edt_msg(DBG2, "pdv_auto_set_roi()\n");
06911 
06912     if ((ret = pdv_set_roi(pdv_p, 0, w, 0, h)) == 0)
06913     {
06914         if (pdv_is_cameralink(pdv_p))
06915             pdv_setsize(pdv_p, pdv_p->dd_p->hactv, pdv_p->dd_p->vactv);
06916         ret = pdv_enable_roi(pdv_p, 1);
06917     }
06918 
06919     return ret;
06920 }
06921 
06939 int
06940 pdv_enable_roi(PdvDev * pdv_p, int flag)
06941 {
06942     u_int   roictl;
06943     Dependent *dd_p = pdv_p->dd_p;
06944 
06945     /* NEW 6/20 -- CL NOT always enabled; modified accordingly */
06946     if (pdv_is_cameralink(pdv_p))
06947     {
06948         if (flag) /* enable */
06949         {
06950             edt_reg_and(pdv_p, PDV_CL_CFG, ~0x08); /* !! bit should have a label */
06951             pdv_setsize(pdv_p, dd_p->hactv, dd_p->vactv);
06952         }
06953         else /* disable */
06954         {
06955             edt_reg_or(pdv_p, PDV_CL_CFG, 0x08);
06956             pdv_setsize(pdv_p, dd_p->cam_width, dd_p->cam_height);
06957         }
06958 
06959         dd_p->roi_enabled = flag;
06960 
06961         return 0;
06962     }
06963 
06964     if (dd_p->xilinx_rev < 2 || dd_p->xilinx_rev > 32)
06965     {
06966         edt_msg(DBG2, "pdv_enable_roi(): can't enable, N/A this xilinx (%x)\n", dd_p->xilinx_rev);
06967         return -1;
06968     }
06969 
06970     edt_msg(DBG2, "pdv_enable_roi(%d): %sabling\n", flag, flag ? "EN" : "DIS");
06971 
06972     /* edt_msleep(100); */
06973 
06974     roictl = edt_reg_read(pdv_p, PDV_ROICTL);
06975 
06976 
06977     if (flag)                   /* enable ROI */
06978     {
06979         roictl |= PDV_ROICTL_ROI_EN;
06980         edt_reg_write(pdv_p, PDV_ROICTL, roictl);
06981         pdv_setsize(pdv_p, dd_p->hactv, dd_p->vactv);
06982     }
06983     else                        /* disable ROI */
06984     {
06985         /* ALERT -- not a R/W reg so can't and/or bits */
06986         roictl &= ~PDV_ROICTL_ROI_EN;
06987         edt_reg_write(pdv_p, PDV_ROICTL, roictl);
06988         pdv_setsize(pdv_p, dd_p->cam_width, dd_p->cam_height);
06989     }
06990 
06991     dd_p->roi_enabled = flag;
06992 
06993     return 0;
06994 }
06995 
07015 int
07016 pdv_access(char *fname, int perm)
07017 {
07018     return edt_access(fname, perm);
07019 }
07020 
07021 
07045 int
07046 pdv_strobe(PdvDev * pdv_p, int count, int delay)
07047 {
07048     Dependent *dd_p = pdv_p->dd_p;
07049 
07050     if (pdv_strobe_method(pdv_p) != PDV_LHS_METHOD1)
07051         return -1;
07052 
07053     edt_msg(DBG2, "pdv_strobe(%d %d)\n", count, delay);
07054 
07055     edt_reg_write(pdv_p, PDV_SHUTTER, delay);
07056 
07057     /*
07058      * write to LSB loads the low byte, write to MSB loads high byte and also
07059      * fires the strobe
07060      */
07061     edt_reg_write(pdv_p, PDV_FIXEDLEN, count);
07062 
07063     return 0;
07064 }
07065 
07086 int
07087 pdv_set_strobe_counters(PdvDev * pdv_p, int count, int delay, int period)
07088 {
07089     Dependent *dd_p = pdv_p->dd_p;
07090 
07091     if (pdv_strobe_method(pdv_p) != PDV_LHS_METHOD2)
07092         return -1;
07093 
07094     if (count > 0xfff)
07095     {
07096         edt_msg(DBG1, "pdv_set_strobe_counters() ERROR -- count out of range\n");
07097         return -1;
07098     }
07099 
07100     if (delay > 0xff)
07101     {
07102         edt_msg(PDVWARN, "pdv_set_strobe_counters() ERROR -- delay out of range\n");
07103         return -1;
07104     }
07105 
07106     if (period > 0xff)
07107     {
07108         edt_msg(PDVWARN, "pdv_set_strobe_counters() ERROR -- period out of range\n");
07109         return -1;
07110     }
07111 
07112     edt_msg(DBG2, "pdv_set_strobe_counters(%d %d %d)\n", count, delay, period);
07113 
07114     edt_reg_write(pdv_p, PDV_LHS_DELAY, delay);
07115 
07116     edt_reg_write(pdv_p, PDV_LHS_PERIOD, period);
07117 
07118     /*
07119      * write to the count (2 bytes, combined)
07120      */
07121     edt_reg_write(pdv_p, PDV_LHS_COUNT, count);
07122 
07123     return 0;
07124 }
07125 
07137 int
07138 pdv_enable_strobe(PdvDev * pdv_p, int ena)
07139 {
07140     int method = pdv_strobe_method(pdv_p);
07141 
07142     if (pdv_p->devid == PDVFOI_ID)
07143         return -1;
07144 
07145     if (method == 0)
07146         return -1;
07147 
07148     if (method == PDV_LHS_METHOD1)
07149     {
07150         if (ena == 0)
07151             return -1;
07152         return 0;
07153     }
07154 
07155     if (ena)
07156         edt_reg_write(pdv_p, PDV_LHS_CONTROL, PDV_LHS_ENABLE);
07157     else edt_reg_write(pdv_p, PDV_LHS_CONTROL, 0);
07158 
07159     return 0;
07160 }
07161 
07172 int
07173 pdv_strobe_method(PdvDev *pdv_p)
07174 {
07175     Dependent *dd_p = pdv_p->dd_p;
07176 
07177     if (dd_p->strobe_enabled == NOT_SET)
07178     {
07179         int reg ;
07180 
07181         /* default to not enabled */
07182         dd_p->strobe_enabled = 0;
07183 
07184         if (pdv_p->devid == PDVFOI_ID)
07185             return 0;
07186 
07187         /* ALERT: figure out somehow whether LH strobe flash is loaded
07188          * but for now just return lhs2 */
07189         if (pdv_p->devid == PDVCL_ID)
07190         {
07191             dd_p->strobe_enabled = PDV_LHS_METHOD2;
07192             return dd_p->strobe_enabled;
07193         }
07194 
07195         /* old xilinx revs didn't have strobe, so just bail out here */
07196         if (dd_p->xilinx_rev < 2 || dd_p->xilinx_rev > 32)
07197             return 0;
07198 
07199         /*
07200          * see if new LHS registers are there (can be written/read)
07201          */
07202         if (!dd_p->register_wrap)
07203         {
07204             reg = edt_reg_read(pdv_p, PDV_LHS_COUNT_HI);
07205             edt_reg_write(pdv_p, PDV_LHS_COUNT_HI, 0x50);
07206             if (edt_reg_read(pdv_p, PDV_LHS_COUNT_HI) == 0x50)
07207             {
07208                 edt_reg_write(pdv_p, PDV_LHS_COUNT_HI, reg);
07209                 dd_p->strobe_enabled = PDV_LHS_METHOD2;
07210                 return dd_p->strobe_enabled;
07211             }
07212         }
07213 
07214         /* still here? okay check for (infer) OLD strobe method */
07215         if (pdv_p->devid != PDVFOI_ID)
07216         {
07217             int     status = edt_reg_read(pdv_p, PDV_SERIAL_DATA_STAT);
07218 
07219             if (status & LHS_DONE)
07220                 dd_p->strobe_enabled = PDV_LHS_METHOD1;
07221         }
07222     }
07223 
07224     return dd_p->strobe_enabled;
07225 }
07226 
07227 
07247 pdv_set_strobe_dac(PdvDev * pdv_p, u_int value)
07248 {
07249     int     i;
07250     int     reg;
07251     int     method;
07252     u_int   mcl, mask;
07253     u_char  data;
07254     Dependent *dd_p = pdv_p->dd_p;
07255 
07256     if ((method = pdv_strobe_method(pdv_p)) == 0)
07257         return -1;
07258 
07259     if (method == PDV_LHS_METHOD2)
07260         reg = PDV_LHS_CONTROL;
07261     else reg = PDV_MODE_CNTL;
07262 
07263     edt_msg(DBG2, "pdv_strobe(%d)\n", value);
07264 
07265     mcl = edt_reg_read(pdv_p, reg) & 0x0f;      /* preserve low bits */
07266 
07267     /*
07268      * dac is high nibble of register with strobe xilinx first we clear, then
07269      * set low bit
07270      */
07271     edt_reg_write(pdv_p, reg, mcl | PDV_LHS_DAC_LOAD);
07272 
07273     /*
07274      * shift in 16 bits
07275      */
07276     for (i = 0; i < 16; i++)
07277     {
07278         mask = (value & (1 << (15 - i)));
07279 
07280         if (mask)
07281             data = PDV_LHS_DAC_DATA;
07282         else
07283             data = 0;
07284 
07285         edt_reg_write(pdv_p, reg, mcl | PDV_LHS_DAC_LOAD | data);
07286         edt_reg_write(pdv_p, reg, mcl | PDV_LHS_DAC_LOAD | PDV_LHS_DAC_CLOCK | data);
07287         edt_reg_write(pdv_p, reg, mcl | PDV_LHS_DAC_LOAD | data);
07288         edt_reg_write(pdv_p, reg, mcl | PDV_LHS_DAC_LOAD);
07289     }
07290 
07291     edt_reg_write(pdv_p, reg, mcl &~ PDV_LHS_DAC_LOAD);
07292     return 0;
07293 }
07294 
07302 void
07303 pdv_flush_channel_fifo(PdvDev * pdv_p)
07304 {
07305 
07306     /* now obsolete channel reset is fixed for FOX 
07307        jsc 3/6/06 */
07308 
07309     pdv_flush_fifo(pdv_p);
07310 }
07311 
07318 void
07319 pdv_flush_fifo(PdvDev * pdv_p)
07320 {
07321         /* previously in comment: @see edt_set_firstflush */
07322     if (pdv_p->devid == PDV_ID ||
07323         pdv_p->devid == PDVK_ID ||
07324         pdv_p->devid == PDVFOI_ID ||
07325         pdv_p->devid == PDVA_ID)
07326     {
07327         edt_flush_fifo(pdv_p);
07328         return;
07329     }
07330 
07331     if (pdv_p->devid == PDVCL_ID)
07332     {
07333         /* RFIFO doesnt exist on camera link */
07334         /* doing the reset intfc here may cause problems */
07335         /* possibly when it happens in same frame as grab - TODO - check */
07336         u_int cfg ;
07337         cfg = edt_intfc_read(pdv_p, PDV_CFG);
07338         cfg &= ~PDV_FIFO_RESET;
07339         edt_intfc_write(pdv_p, PDV_CFG, (u_char) (cfg | PDV_FIFO_RESET));
07340         edt_intfc_write(pdv_p, PDV_CMD, PDV_RESET_INTFC);
07341         edt_intfc_write(pdv_p, PDV_CFG, cfg);
07342     }
07343     else if  (pdv_p->devid == PDVFOI_ID)
07344     {
07345         char tmpbuf[10];
07346         int ret;
07347 
07348         ret = pdv_serial_wait(pdv_p, 100, 0);
07349         if (ret > 10)
07350             pdv_reset_serial(pdv_p);
07351         else
07352             pdv_serial_read(pdv_p, tmpbuf, ret);
07353     }
07354     else
07355     {
07356     /* DV-FOX, PCIe C-Link */
07357 
07358         u_int cfg ;
07359         cfg = edt_intfc_read(pdv_p, PDV_CFG);
07360         cfg &= ~PDV_FIFO_RESET;
07361         edt_intfc_write(pdv_p, PDV_CFG, (u_char) (cfg | PDV_FIFO_RESET));
07362         edt_flush_channel(pdv_p, pdv_p->channel_no);
07363         edt_intfc_write(pdv_p, PDV_CFG, cfg);
07364     }
07365 }
07366 
07370 void
07371 pdv_setup_continuous_channel(PdvDev * pdv_p)
07372 
07373 {
07374     /* now obsolete channel reset is fixed for FOX 
07375        jsc 3/6/06 */
07376     pdv_setup_continuous(pdv_p);
07377 }
07378 
07387 void
07388 pdv_setup_continuous(PdvDev * pdv_p)
07389 {
07390     pdv_flush_fifo(pdv_p);
07391 
07392     if (pdv_p->devid == PDV_ID ||
07393         pdv_p->devid == PDVK_ID ||
07394         pdv_p->devid == PDVA_ID)
07395     {
07396 
07397         if (edt_get_firstflush(pdv_p) != EDT_ACT_KBS)
07398                 edt_set_firstflush(pdv_p, EDT_ACT_ONCE);
07399     }
07400     else
07401     {
07402         edt_set_firstflush(pdv_p,EDT_ACT_NEVER) ;
07403         edt_set_autodir(pdv_p, 0) ;
07404  
07405     }
07406 
07407     edt_startdma_reg(pdv_p, PDV_CMD, PDV_ENABLE_GRAB);
07408 
07409     if (pdv_in_continuous(pdv_p))
07410     {
07411         /* pdv_start_hardware_continuous(pdv_p) ; */
07412         edt_set_continuous(pdv_p, 1);
07413     }
07414     else if (pdv_p->dd_p->fv_once)
07415     {
07416         pdv_start_hardware_continuous(pdv_p);
07417     }
07418     else
07419         edt_set_continuous(pdv_p, 0);
07420 
07421     pdv_p->dd_p->started_continuous = 1;
07422 
07423 }
07424 
07432 void
07433 pdv_stop_continuous(PdvDev * pdv_p)
07434 {
07435 
07436     if (pdv_in_continuous(pdv_p))
07437     {
07438         edt_set_continuous(pdv_p, 0);
07439     }
07440     else if (pdv_p->dd_p->fv_once)
07441         pdv_stop_hardware_continuous(pdv_p); 
07442 
07443     pdv_p->dd_p->started_continuous = 0;
07444 
07445     if (pdv_p->devid == PDVFOI_ID)
07446     {
07447         char    tmpbuf[10];
07448         int     ret;
07449 
07450         ret = pdv_serial_wait(pdv_p, 100, 0);
07451         if (ret > 10)
07452             pdv_reset_serial(pdv_p);
07453         else
07454             pdv_serial_read(pdv_p, tmpbuf, ret);
07455     }
07456 }
07457 
07478 int
07479 pdv_timeout_restart(PdvDev * pdv_p, int restart)
07480 {
07481     int     curdone, curtodo;
07482 
07483     curdone = edt_done_count(pdv_p);
07484     curtodo = edt_get_todo(pdv_p);
07485 
07486     edt_abort_dma(pdv_p);
07487     pdv_stop_continuous(pdv_p);
07488 
07489     edt_set_buffer(pdv_p, curdone);
07490     edt_reg_write(pdv_p, PDV_CMD, PDV_RESET_INTFC);
07491     pdv_setup_continuous(pdv_p);
07492 
07493     if (restart && 
07494         (curtodo - curdone))
07495         pdv_start_images(pdv_p, curtodo - curdone);
07496 
07497     return curtodo - curdone;
07498 }
07499  /* end acquisition */
07501 
07502 /* for debug printfs only */
07503 static char hs[128];
07504 static char *
07505 hex_to_str(char *resp, int n)
07506 {
07507 
07508     int     i;
07509     char   *p = hs;
07510 
07511     for (i = 0; i < n; i++)
07512     {
07513         sprintf(p, "%02x ", resp[i]);
07514         p += 3;
07515     }
07516     *p = '\0';
07517     return hs;
07518 }
07519 
07520 
07531 int
07532 pdv_get_min_shutter(PdvDev * pdv_p)
07533 
07534 {
07535     return pdv_p->dd_p->shutter_speed_min;
07536 }
07537 
07538 
07547 int
07548 pdv_get_max_shutter(PdvDev * pdv_p)
07549 
07550 {
07551     return pdv_p->dd_p->shutter_speed_max;
07552 }
07553 
07554 
07565 int
07566 pdv_get_min_gain(PdvDev * pdv_p)
07567 
07568 {
07569     return pdv_p->dd_p->gain_min;
07570 }
07571 
07572 
07582 int
07583 pdv_get_max_gain(PdvDev * pdv_p)
07584 
07585 {
07586     return pdv_p->dd_p->gain_max;
07587 }
07588 
07589 
07599 int
07600 pdv_get_min_offset(PdvDev * pdv_p)
07601 
07602 {
07603     return pdv_p->dd_p->offset_min;
07604 }
07605 
07606 
07616 int
07617 pdv_get_max_offset(PdvDev * pdv_p)
07618 
07619 {
07620     return pdv_p->dd_p->offset_max;
07621 }
07622 
07627 void
07628 pdv_send_break(PdvDev * pdv_p)
07629 {
07630     u_int   reg;
07631 
07632     edt_msg(DBG2, "pdv_send_break()");
07633 
07634     reg = edt_reg_read(pdv_p, PDV_UTIL2);
07635     edt_reg_write(pdv_p, PDV_UTIL2, reg & ~PDV_MC4);
07636     edt_reg_write(pdv_p, PDV_UTIL2, (reg | PDV_SEL_MC4) & ~PDV_MC4);
07637     edt_msleep(500);
07638     edt_reg_write(pdv_p, PDV_UTIL2, reg & ~PDV_SEL_MC4 & ~PDV_MC4);
07639     edt_reg_write(pdv_p, PDV_UTIL2, reg);
07640 }
07641 
07642 static void
07643 pdv_trigger_specinst(PdvDev * pdv_p)
07644 {
07645     char    cmd = pdv_p->dd_p->serial_trigger[0];
07646 
07647     edt_msg(DBG2, "pdv_trigger_specinst('%c')\n", cmd);
07648 
07649     pdv_serial_binary_command(pdv_p, &cmd, 1);
07650 
07651 }
07652 
07656 static void
07657 pdv_posttrigger_specinst(PdvDev * pdv_p)
07658 {
07659     char    cmd = pdv_p->dd_p->serial_trigger[0];
07660     char    resp[32];
07661     int     ret;
07662     int     waitcnt = 2;
07663 
07664     resp[0] = resp[1] = resp[2] = 0;
07665 
07666 #ifdef SPECINST_WAS
07667     if (pdv_p->devid == PDVFOI_ID)
07668         waitcnt += 2;
07669     if ((ret = pdv_serial_wait(pdv_p, 1500, waitcnt)) == waitcnt)
07670         pdv_serial_read(pdv_p, resp, ret);
07671 #else
07672     if (pdv_p->devid == PDVFOI_ID)
07673         pdv_serial_wait_next(pdv_p, 2000, 0);
07674     else
07675         pdv_serial_wait_next(pdv_p, 2000, 1);
07676     ret = pdv_serial_read(pdv_p, resp, 2);
07677 #endif
07678 
07679     if ((ret != waitcnt)
07680         || (resp[0] != pdv_p->dd_p->serial_trigger[0])
07681         || (resp[1] != pdv_p->dd_p->serial_response[0]))
07682     {
07683         edt_msg(PDVWARN, "\npdv_posttrigger_specinst: invalid or missing serial\n");
07684         edt_msg(PDVWARN, "response (sent %c, ret %d s/b %d, resp <%s>)\n", cmd, ret, waitcnt, (ret > 0) ? resp : "");
07685         return;
07686     }
07687 }
07688 
07689 static int
07690 pdv_specinst_serial_triggered(PdvDev * pdv_p)
07691 {
07692     if (((pdv_p->dd_p->camera_shutter_timing == SPECINST_SERIAL)
07693          || (pdv_p->dd_p->camera_shutter_speed == SPECINST_SERIAL))
07694         && (pdv_p->dd_p->serial_trigger[0]))
07695         return 1;
07696     return 0;
07697 }
07698 
07699 int
07700 pdv_pause_for_serial(PdvDev * pdv_p)
07701 {
07702     return pdv_p->dd_p->pause_for_serial;
07703 }
07704 
07705 
07706 int
07707 isafloat(char *str)
07708 {
07709     unsigned int i;
07710     int     numdots = 0;
07711     int     numchars = 0;
07712 
07713     for (i = 0; i < strlen(str); i++)
07714     {
07715         if (str[i] == '.')
07716             ++numdots;
07717         else if (isdigit(str[i]))
07718             ++numchars;
07719         else
07720             return 0;
07721     }
07722 
07723     if (numdots == 1 && numchars > 0)
07724         return 1;
07725     return 0;
07726 }
07727 
07728 int
07729 isdigits(char *str)
07730 {
07731     unsigned int i;
07732     int     numchars = 0;
07733 
07734     for (i = 0; i < strlen(str); i++)
07735     {
07736         if (isdigit(str[i]))
07737             ++numchars;
07738         else if ((str[i] == '-') && (i == 0))
07739             ;
07740         else
07741             return 0;
07742     }
07743 
07744     if (numchars > 0)
07745         return 1;
07746     return 0;
07747 }
07748 
07749 int
07750 isxdigits(char *str)
07751 {
07752     unsigned int i;
07753     int     numchars = 0;
07754 
07755     for (i = 0; i < strlen(str); i++)
07756     {
07757         if (isxdigit(str[i]))
07758             ++numchars;
07759         else
07760             return 0;
07761     }
07762 
07763     if (numchars > 0)
07764         return 1;
07765     return 0;
07766 }
07767 
07775 int
07776 pdv_is_kodak_i(PdvDev * pdv_p)
07777 {
07778     Dependent *dd_p = pdv_p->dd_p;
07779 
07780     if ((strcmp(dd_p->serial_exposure, "EXE") == 0)
07781         || (strcmp(dd_p->serial_gain, "DGN") == 0)
07782         || (strcmp(dd_p->serial_offset, "GAE") == 0)
07783         || (strcmp(dd_p->serial_offset, "BKE") == 0))
07784         return 1;
07785     return 0;
07786 }
07787 
07788 
07799 int
07800 pdv_is_atmel(PdvDev * pdv_p)
07801 {
07802     Dependent *dd_p = pdv_p->dd_p;
07803 
07804     if ((strncasecmp(dd_p->camera_class, "Atmel", 5) == 0)
07805         || (strncmp(dd_p->serial_exposure, "I=", 2) == 0))
07806         return 1;
07807     return 0;
07808 }
07809 
07817 int
07818 pdv_is_hamamatsu(PdvDev * pdv_p)
07819 {
07820     Dependent *dd_p = pdv_p->dd_p;
07821 
07822     if ((strncasecmp(dd_p->camera_class, "Hamamatsu", 9) == 0)
07823         || (strncmp(dd_p->serial_exposure, "SHT", 3) == 0)
07824         || (strncmp(dd_p->serial_exposure, "FBL", 3) == 0)
07825         || (strncmp(dd_p->serial_exposure, "AET", 3) == 0))
07826         return 1;
07827     return 0;
07828 }
07829 
07830 
07831 
07832 pdv_update_values_from_camera(PdvDev * pdv_p)
07833 {
07834     int     ret = 0;
07835 
07836     if (pdv_is_kodak_i(pdv_p))
07837         ret = pdv_update_from_kodak_i(pdv_p);
07838     else if (pdv_is_dvc(pdv_p))
07839         ret = pdv_update_from_dvc(pdv_p);
07840     else if (pdv_is_atmel(pdv_p))
07841         ret = pdv_update_from_atmel(pdv_p);
07842     else if (pdv_is_hamamatsu(pdv_p))
07843         ret = pdv_update_from_hamamatsu(pdv_p);
07844     /* add more here */
07845     else
07846         ret = -1;
07847 
07848     return ret;
07849 }
07850 
07851 int
07852 pdv_update_from_kodak_i(PdvDev * pdv_p)
07853 {
07854     int     i, n, ret = 0;
07855     char   *stat[64];
07856     char  **stat_p = stat;
07857     Dependent *dd_p = pdv_p->dd_p;
07858 
07859     for (i = 0; i < 64; i++)
07860     {
07861         *stat_p = (char *) malloc(64 * sizeof(char));
07862         **stat_p = '\0';
07863         ++stat_p;
07864     }
07865 
07866     if ((n = pdv_query_serial(pdv_p, "STS?", stat)) < 1)
07867         ret = -1;
07868     else
07869     {
07870         update_int_from_serial(stat, n, "BKE", &dd_p->level);
07871         update_int_from_serial(stat, n, "GAE", &dd_p->gain);
07872         update_int_from_serial(stat, n, "DGN", &dd_p->gain);
07873         update_int_from_serial(stat, n, "EXE", &dd_p->shutter_speed);
07874         update_int_from_serial(stat, n, "BNS", &dd_p->binx);
07875         update_int_from_serial(stat, n, "BNS", &dd_p->biny);
07876     }
07877 
07878     for (i = 0; i < 64; i++)
07879         free(stat[i]);
07880 
07881     return ret;
07882 }
07883 
07884 int
07885 pdv_update_from_hamamatsu(PdvDev * pdv_p)
07886 {
07887     int     i, n, ret = 0;
07888     char   *stat[64];
07889     char  **stat_p = stat;
07890     Dependent *dd_p = pdv_p->dd_p;
07891 
07892     for (i = 0; i < 64; i++)
07893     {
07894         *stat_p = (char *) malloc(64 * sizeof(char));
07895         **stat_p = '\0';
07896         ++stat_p;
07897     }
07898 
07899     if ((n = pdv_query_serial(pdv_p, "?CEG", stat)) < 1)
07900         ret = -1;
07901     else
07902         update_int_from_serial(stat, n, "CEG", &dd_p->gain);
07903 
07904     if ((n = pdv_query_serial(pdv_p, "?CEO", stat)) < 1)
07905         ret = -1;
07906     else
07907         update_int_from_serial(stat, n, "CEO", &dd_p->level);
07908 
07909     if ((n = pdv_query_serial(pdv_p, "?SHT", stat)) < 1)
07910         ret = -1;
07911     else
07912         update_int_from_serial(stat, n, "SHT", &dd_p->shutter_speed);
07913 
07914     for (i = 0; i < 64; i++)
07915         free(stat[i]);
07916 
07917     return ret;
07918 }
07919 
07920 
07921 int
07922 pdv_update_from_atmel(PdvDev * pdv_p)
07923 {
07924     int     i, n, ret = 0;
07925     int     tmpval;
07926     char   *stat[64];
07927     char  **stat_p = stat;
07928     Dependent *dd_p = pdv_p->dd_p;
07929 
07930     for (i = 0; i < 64; i++)
07931     {
07932         *stat_p = (char *) malloc(64 * sizeof(char));
07933         **stat_p = '\0';
07934         ++stat_p;
07935     }
07936 
07937     if ((n = pdv_query_serial(pdv_p, "!=3", stat)) < 1)
07938         ret = -1;
07939     else
07940     {
07941         update_int_from_serial(stat, n, "G", &dd_p->gain);
07942         update_int_from_serial(stat, n, "I", &dd_p->shutter_speed);
07943         if (update_int_from_serial(stat, n, "B", &tmpval) == 0)
07944             dd_p->binx = dd_p->biny = tmpval + 1;
07945     }
07946 
07947     for (i = 0; i < 64; i++)
07948         free(stat[i]);
07949 
07950     return ret;
07951 }
07952 
07959 int
07960 pdv_query_serial(PdvDev * pdv_p, char *cmd, char **resp)
07961 {
07962 
07963     char   *buf_p;
07964     char    buf[2048];
07965     char    *tmp_storage;
07966     int     length;
07967     int     ret;
07968     int     i, j, l;
07969     int     nfound = 0;
07970 
07971     if ((tmp_storage = (char *)malloc(strlen(cmd)+1)) == NULL)
07972         return 0;
07973     sprintf(tmp_storage, "%s\r", cmd);
07974     edt_msg(DBG2, "pdv_query_serial: writing <%s>\n", cmd);
07975     pdv_serial_command(pdv_p, tmp_storage);
07976 
07977     /*
07978      * serial_timeout comes from the config file (or -t override flag in this
07979      * app), or if not present defaults to 500
07980      */
07981     pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, 64);
07982 
07983     /*
07984      * get the return string. How its printed out depends on whether its 1)
07985      * ASCII, 2) HEX, or 3) Pulnix STX/ETX format
07986      */
07987     buf_p = buf;
07988     length = 0;
07989     do
07990     {
07991         ret = pdv_serial_read(pdv_p, buf_p, 2048 - length);
07992         edt_msg(DBG2, "read returned %d\n", ret);
07993 
07994         if (ret != 0)
07995         {
07996             buf_p[ret + 1] = 0;
07997             buf_p += ret;
07998             length += ret;
07999         }
08000         if (pdv_p->devid == PDVFOI_ID)
08001             pdv_serial_wait(pdv_p, 500, 0);
08002         else
08003             pdv_serial_wait(pdv_p, 500, 64);
08004     } while (ret > 0);
08005 
08006     /*
08007      * copy the buffer to the string list
08008      */
08009     i = 0;
08010     j = 0;
08011     buf_p = buf;
08012     for (l = 0; l < length; l++)
08013     {
08014         if ((*buf_p == '\n') || (*buf_p == '\r'))
08015         {
08016             if (j != 0)
08017             {
08018                 resp[i++][j] = '\0';
08019                 j = 0;
08020             }
08021         }
08022         else
08023         {
08024             if (j == 0)
08025                 ++nfound;
08026             resp[i][j++] = *buf_p;
08027             resp[i][j] = '\0';
08028         }
08029 
08030         ++buf_p;
08031     }
08032     return nfound;
08033 }
08034 
08039 static int
08040 update_int_from_serial(char **stat, int nstats, char *cmd, int *value)
08041 {
08042     int     i, ret = -1;
08043     int     len = (int) strlen(cmd);
08044     double  tmpf;
08045     char   *arg;
08046 
08047     /*
08048      * expected format: "CMD NN or CMD -NN or CMD F.F or CMD=N"
08049      */
08050     for (i = 0; i < nstats; i++)
08051     {
08052         arg = &stat[i][len + 1];
08053         if ((strncmp(stat[i], cmd, len) == 0)
08054             && ((stat[i][len] == ' ') || (stat[i][len] == '=')))
08055         {
08056             if (isdigits(arg))
08057             {
08058                 *value = atoi(arg);
08059                 ret = 0;
08060             }
08061             /* special case kodak 'i' decimal EXE */
08062             else if ((isafloat(arg) && strncmp(cmd, "EXE", 3) == 0))
08063             {
08064                 tmpf = atof(arg);
08065                 *value = (int) (tmpf / 0.063);
08066                 ret = 0;
08067             }
08068         }
08069     }
08070     return ret;
08071 }
08072 
08077 static int
08078 update_string_from_serial(char **stat, int nstats, char *cmd, char *value, int maxlen)
08079 {
08080     int     i, ret = -1;
08081     int     len = (int) strlen(cmd);
08082     char   *arg;
08083 
08084     /*
08085      * expected format: "CMD NN or CMD -NN or CMD F.F or CMD=N"
08086      */
08087     for (i = 0; i < nstats; i++)
08088     {
08089         arg = &stat[i][len + 1];
08090         if ((strncmp(stat[i], cmd, len) == 0)
08091             && ((stat[i][len] == ' ') || (stat[i][len] == '=')))
08092         {
08093             strncpy(value, stat[i] + len + 1, maxlen);
08094         }
08095     }
08096     return ret;
08097 }
08098 
08103 static void
08104 update_2dig_from_serial(char **stat, int nstats, char *cmd, int *val1, int *val2)
08105 {
08106     int     i;
08107     int     len = (int) strlen(cmd);
08108     char   *arg;
08109 
08110     /*
08111      * expected format: "CMD XY"
08112      */
08113     for (i = 0; i < nstats; i++)
08114     {
08115         arg = &stat[i][len + 1];
08116         if ((strncmp(stat[i], cmd, len) == 0)
08117             && (stat[i][len] == ' '))
08118         {
08119             if (isdigits(arg) && strlen(arg) == 2)
08120             {
08121                 *val1 = arg[0] - '0';
08122                 *val2 = arg[1] - '0';
08123             }
08124         }
08125     }
08126 }
08127 
08132 static void
08133 update_hex_from_serial(char **stat, int nstats, char *cmd, int *value)
08134 {
08135     int     i;
08136     size_t     len = strlen(cmd);
08137     char   *arg;
08138 
08139     /*
08140      * expected format: "CMD XX"
08141      */
08142     for (i = 0; i < nstats; i++)
08143     {
08144         arg = &stat[i][len + 1];
08145         if ((strncmp(stat[i], cmd, len) == 0)
08146             && (stat[i][len] == ' '))
08147         {
08148             if (isxdigits(arg))
08149             {
08150                 *value = strtol(arg, NULL, 16);
08151             }
08152         }
08153     }
08154 }
08155 
08156 
08168 int 
08169 pdv_set_mode(PdvDev * pdv_p, char *mode, int mcl)
08170 {
08171     edt_msg(PDVWARN, "pdv_set_aperture is OBSOLETE\n");
08172     return -1;
08173 }
08174 
08175 
08176 int 
08177 pdv_set_mode_atmel(PdvDev * pdv_p, char *mode)
08178 {
08179     Dependent *dd_p = pdv_p->dd_p;
08180     int     cfg = 0;
08181     int     cont = 0;
08182 
08183     if ((strcmp(mode, "T=0") == 0)      /* CONTINUOUS */
08184         || (strcmp(mode, "T=1") == 0))
08185     {
08186         if (strcmp(mode, "T=0") == 0)
08187         {
08188             dd_p->shutter_speed_min = 0;
08189             dd_p->shutter_speed_max = 0;
08190         }
08191         else
08192         {
08193             dd_p->shutter_speed_min = 1;
08194             dd_p->shutter_speed_max = 2000;
08195         }
08196         dd_p->camera_shutter_timing = AIA_SERIAL;
08197         dd_p->trig_pulse = 1;   /* probably N/A but its in the cfg so
08198                                  * whatever */
08199         dd_p->mode_cntl_norm = 0x0;
08200         edt_reg_write(pdv_p, PDV_MODE_CNTL, dd_p->mode_cntl_norm);
08201         cfg = edt_reg_read(pdv_p, PDV_CFG) | PDV_TRIG | PDV_INV_SHUTTER;
08202         edt_reg_write(pdv_p, PDV_CFG, cfg);
08203         pdv_serial_command(pdv_p, mode);
08204         strcpy(dd_p->serial_exposure, "I=");
08205     }
08206     else if (strcmp(mode, "T=2") == 0)  /* TRIGGERED */
08207     {
08208         dd_p->timeout_multiplier = 1;
08209         dd_p->shutter_speed_min = 1;
08210         dd_p->shutter_speed_max = 0x414;
08211         dd_p->camera_shutter_timing = AIA_SERIAL;
08212         dd_p->trig_pulse = 1;
08213         dd_p->mode_cntl_norm = 0x10;
08214         edt_reg_write(pdv_p, PDV_MODE_CNTL, dd_p->mode_cntl_norm);
08215         cfg = edt_reg_read(pdv_p, PDV_CFG) | PDV_TRIG;
08216         edt_reg_write(pdv_p, PDV_CFG, cfg);
08217         pdv_serial_command(pdv_p, mode);
08218         strcpy(dd_p->serial_exposure, "I=");
08219     }
08220     else if (strcmp(mode, "T=3") == 0)  /* CONTOLLED (camelia linescan only?) */
08221     {
08222         dd_p->timeout_multiplier = 1;
08223         dd_p->shutter_speed_min = 1;
08224         dd_p->shutter_speed_max = 25500;
08225         dd_p->camera_shutter_timing = AIA_MCL;
08226         dd_p->trig_pulse = 0;
08227         dd_p->mode_cntl_norm = 0x10;
08228         edt_reg_write(pdv_p, PDV_MODE_CNTL, dd_p->mode_cntl_norm);
08229         cfg = edt_reg_read(pdv_p, PDV_CFG) & ~PDV_TRIG;
08230         edt_reg_write(pdv_p, PDV_CFG, cfg);
08231         pdv_serial_command(pdv_p, mode);
08232         dd_p->serial_exposure[0] = '\0';
08233     }
08234     else                        /* UNKNOWN */
08235     {
08236         edt_msg(PDVWARN, "WARNING: unsupported ATMEL mode: %s\n", mode);
08237         return -1;
08238     }
08239     return 0;
08240 }
08241 
08245 int 
08246 pdv_set_mode_kodak(PdvDev * pdv_p, char *mode)
08247 {
08248     Dependent *dd_p = pdv_p->dd_p;
08249     char    cmd[32];
08250     int     cfg = 0;
08251     int     cont = 0;
08252 
08253     if (strcmp(mode, "CS") == 0)/* CONTINUOUS */
08254     {
08255         dd_p->shutter_speed_min = 1;
08256         dd_p->shutter_speed_max = 512;
08257         dd_p->camera_shutter_timing = AIA_SERIAL;
08258         dd_p->trig_pulse = 1;   /* probably N/A but its in the cfg so
08259                                  * whatever */
08260         dd_p->mode_cntl_norm = 0x0;
08261         edt_reg_write(pdv_p, PDV_MODE_CNTL, dd_p->mode_cntl_norm);
08262         cfg = edt_reg_read(pdv_p, PDV_CFG) | PDV_TRIG | PDV_INV_SHUTTER;
08263         edt_reg_write(pdv_p, PDV_CFG, cfg);
08264         sprintf(cmd, "MDE %s", mode);
08265         pdv_serial_command(pdv_p, cmd);
08266         strcpy(dd_p->serial_exposure, "EXE");
08267     }
08268     else if (strcmp(mode, "TR") == 0)   /* TRIGGERED */
08269     {
08270         dd_p->shutter_speed_min = 1;
08271         dd_p->shutter_speed_max = 255;
08272         dd_p->camera_shutter_timing = AIA_SERIAL;
08273         dd_p->trig_pulse = 1;
08274         dd_p->mode_cntl_norm = 0x10;
08275         edt_reg_write(pdv_p, PDV_MODE_CNTL, dd_p->mode_cntl_norm);
08276         cfg = edt_reg_read(pdv_p, PDV_CFG) | PDV_TRIG;
08277         edt_reg_write(pdv_p, PDV_CFG, cfg);
08278         sprintf(cmd, "MDE %s", mode);
08279         pdv_serial_command(pdv_p, cmd);
08280         strcpy(dd_p->serial_exposure, "EXE");
08281     }
08282     else if (strcmp(mode, "CD") == 0)   /* CONTROLLED */
08283     {
08284         dd_p->shutter_speed_min = 1;
08285         dd_p->shutter_speed_max = 25500;
08286         dd_p->camera_shutter_timing = AIA_MCL;
08287         dd_p->trig_pulse = 0;
08288         dd_p->mode_cntl_norm = 0x10;
08289         edt_reg_write(pdv_p, PDV_MODE_CNTL, dd_p->mode_cntl_norm);
08290         cfg = edt_reg_read(pdv_p, PDV_CFG) & ~PDV_TRIG;
08291         edt_reg_write(pdv_p, PDV_CFG, cfg);
08292         sprintf(cmd, "MDE %s", mode);
08293         pdv_serial_command(pdv_p, cmd);
08294         dd_p->serial_exposure[0] = '\0';
08295     }
08296     else                        /* PDI, PDP...? */
08297     {
08298         edt_msg(PDVWARN, "WARNING: unsupported DVC mode: %s\n", mode);
08299         return -1;
08300     }
08301     return 0;
08302 }
08303 
08304 int 
08305 pdv_set_mode_hamamatsu(PdvDev * pdv_p, char *mode)
08306 {
08307     Dependent *dd_p = pdv_p->dd_p;
08308     int     cfg = 0;
08309     int     cont = 0;
08310 
08311     /* stub */
08312 
08313     return 0;
08314 
08315 }
08316  /* end settings */
08318 
08319 
08320 /*************************************************************
08321  * DVC Camera Functions
08322  *************************************************************/
08323 
08331 int
08332 pdv_is_dvc(PdvDev * pdv_p)
08333 {
08334     Dependent *dd_p = pdv_p->dd_p;
08335 
08336     if ((strncasecmp(dd_p->camera_class, "DVC", 3) == 0)
08337         || (strncmp(dd_p->serial_exposure, "EXP", 3) == 0))
08338         return 1;
08339     return 0;
08340 }
08341 
08350 int
08351 pdv_set_binning_dvc(PdvDev * pdv_p, int xval, int yval)
08352 {
08353     int     ret = 0;
08354     char    cmdstr[64];
08355     Dependent *dd_p = pdv_p->dd_p;
08356 
08357     sprintf(cmdstr, "%s %d%d", dd_p->serial_binning, yval, xval);
08358 
08359     pdv_serial_command(pdv_p, cmdstr);
08360 
08361     return (ret);
08362 }
08363 
08364 int
08365 pdv_update_from_dvc(PdvDev * pdv_p)
08366 {
08367     int     i, n, ret = 0;
08368     char   *stat[64];
08369     char  **stat_p = stat;
08370     Dependent *dd_p = pdv_p->dd_p;
08371 
08372     for (i = 0; i < 64; i++)
08373     {
08374         *stat_p = (char *) malloc(64 * sizeof(char));
08375         **stat_p = '\0';
08376         ++stat_p;
08377     }
08378 
08379     if ((n = pdv_query_serial(pdv_p, "STA", stat)) < 1)
08380         ret = -1;
08381     else
08382     {
08383         update_hex_from_serial(stat, n, "OFS", &dd_p->level);
08384         update_hex_from_serial(stat, n, "GAI", &dd_p->gain);
08385         update_hex_from_serial(stat, n, "EXP", &dd_p->shutter_speed);
08386         update_2dig_from_serial(stat, n, "BIN", &dd_p->binx, &dd_p->biny);
08387     }
08388 
08389     for (i = 0; i < 64; i++)
08390         free(stat[i]);
08391 
08392     return ret;
08393 }
08394 
08395 
08396 int 
08397 pdv_set_mode_dvc(PdvDev * pdv_p, char *mode)
08398 {
08399     Dependent *dd_p = pdv_p->dd_p;
08400     char    cmd[32];
08401     int     cfg = 0;
08402     int     cont = 0;
08403 
08404     if ((strcmp(mode, "NOR") == 0)      /* CONTINUOUS */
08405         || (strcmp(mode, "ULT") == 0)
08406         || (strcmp(mode, "HNL") == 0)
08407         || (strcmp(mode, "HDL") == 0)
08408         || (strcmp(mode, "NFR") == 0)
08409         || (strcmp(mode, "NRR") == 0))
08410     {
08411         if (mode[0] == 'H')     /* one of the high-speed modes */
08412         {
08413             dd_p->shutter_speed_min = 1;
08414             dd_p->shutter_speed_max = 0x414;
08415         }
08416         else
08417         {
08418             if (strcmp(mode, "ULT") == 0)       /* ultra long term */
08419                 dd_p->timeout_multiplier = 10;
08420             else if (strcmp(mode, "NFR") == 0)  /* fra