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 #include "libedt_timing.h"
00284 
00285 #ifdef _NT_
00286 #define strncasecmp strnicmp
00287 #endif
00288 
00289 /* shorthand debug level */
00290 #define PDVWARN PDVLIB_MSG_WARNING
00291 #define PDVFATAL PDVLIB_MSG_FATAL
00292 #define DBG1 PDVLIB_MSG_INFO_1
00293 #define DBG2 PDVLIB_MSG_INFO_2
00294 
00295 int Pdv_debug = 0;
00296 int     Smd_type = NOT_SET;
00297 int     Smd_rate = NOT_SET;
00298 
00299 /*
00300 * library routines
00301 */
00302 
00303 
00304 #define PDV_DEPENDENT(pdv_p) ((pdv_p)->dd_p)
00305 
00306 static void
00307 debug_print_serial_command(char *cmd);
00308 static void
00309 send_serial_binary_cmd(PdvDev * pdv_p, char *hexstr, int value);
00310 
00311 static void pdv_trigger_specinst(PdvDev * pdv_p);
00312 static void pdv_posttrigger_specinst(PdvDev * pdv_p);
00313 static int pdv_specinst_setparam(PdvDev * pdv_p, char cmd, u_long offset, u_long value);
00314 
00318 static int pdv_set_exposure_specinst(PdvDev * pdv_p, int value);
00319 static int pdv_set_gain_specinst(PdvDev * pdv_p, int value);
00320 static int pdv_set_exposure_adimec(PdvDev * pdv_p, int value);
00321 static int pdv_set_exposure_su320(PdvDev * pdv_p, int value);
00322 static int pdv_set_gain_adimec(PdvDev * pdv_p, int value);
00323 static int pdv_set_blacklevel_adimec(PdvDev * pdv_p, int value);
00324 static int pdv_set_exposure_smd(PdvDev * pdv_p, int value);
00325 static int pdv_set_exposure_timc1001pf(PdvDev * pdv_p, int value);
00326 static int pdv_set_exposure_ptm6710_1020(PdvDev * pdv_p, int value);
00327 static int pdv_set_gain_ptm6710_1020(PdvDev * pdv_p, int value);
00328 static int pdv_set_binning_generic(PdvDev * pdv_p, int value);
00329 static int pdv_set_gain_smd(PdvDev * pdv_p, int value);
00330 static int pdv_set_blacklevel_smd(PdvDev * pdv_p, int value);
00331 static int pdv_set_gain_hc8484(PdvDev * pdv_p, int value);
00332 static int pdv_set_exposure_toshiba(PdvDev * pdv_p, int value);
00333 static int pdv_set_gain_toshiba(PdvDev * pdv_p, int value);
00334 static int pdv_set_exposure_cohu(PdvDev * pdv_p, int value);
00335 static int pdv_set_gain_cohu(PdvDev * pdv_p, int value);
00336 static int pdv_set_blacklevel_cohu(PdvDev * pdv_p, int value);
00339 static int pdv_specinst_serial_triggered(PdvDev * pdv_p);
00340 static void CheckSumMessage(unsigned char *msg);
00341 int     pdv_auto_set_timeout(PdvDev * pdv_p);
00342 static int isafloat(char *str);
00343 static int isdigits(char *str);
00344 static int isxdigits(char *str);
00345 static int update_int_from_serial(char **stat, int nstat, char *str, int *value);
00346 static int update_string_from_serial(char **stat, int nstat, char *str, char *value, int maxlen);
00347 static void update_hex_from_serial(char **stat, int nstat, char *str, int *value);
00348 static void update_2dig_from_serial(char **stat, int nstat, char *str, int *val1, int *val2);
00349 int     edt_get_rtimeout(PdvDev * pdv_p);
00350 static int pdv_update_from_kodak_i(PdvDev * pdv_p);
00351 
00352 static int pdv_update_from_atmel(PdvDev * pdv_p);
00353 static int pdv_update_from_hamamatsu(PdvDev * pdv_p);
00354 #ifdef IS_UNUSED
00355 static int pdv_set_mode_atmel(PdvDev * pdv_p, char *mode);
00356 static int pdv_set_mode_hamamatsu(PdvDev * pdv_p, char *mode);
00357 #endif
00358 
00359 static int pdv_set_exposure_timc1001pf(PdvDev * pdv_p, int value);
00360 
00361 int     pdv_query_serial(PdvDev * pdv_p, char *cmd, char **resp);
00362 
00363 /* from pdv_interlace.c */
00364 
00365 void    pdv_dmy_data(void *buf, int width, int height, int depth);
00366 void    pdv_alloc_tmpbuf(PdvDev * pdv_p);
00367 extern  int pdv_process_inplace(PdvDev *pdv_p);
00368 int     pdv_update_size(PdvDev * pdv_p);
00369 
00370 static char *hex_to_str(char *resp, int n);
00371 
00372 #ifdef DOXYGEN_SHOW_UNDOC
00373 
00378 #endif
00379 
00439 PdvDev *
00440 pdv_open_channel(const char *dev_name, int unit, int channel)
00441 {
00442     PdvDev *pdv_p;
00443     char    tmpname[64];
00444     Dependent *dd_p;
00445     static char *debug_env = NULL;
00446     int     level;
00447 
00448     if ((debug_env == NULL)
00449         && ((debug_env = (char *) getenv("PDVDEBUG")) != NULL)
00450         && *debug_env != '0')
00451     {
00452         Pdv_debug = atoi(debug_env);
00453         level = edt_msg_default_level();
00454         if (Pdv_debug > 0)
00455         {
00456             level |= DBG1;
00457             level |= DBG2;
00458         }
00459         edt_msg_set_level(edt_msg_default_handle(), level);
00460 
00461         edt_msg(DBG2, "environment DEBUG set to %d: enabling debug in pdvlib\n", Pdv_debug);
00462     }
00463 
00464     edt_msg(DBG2, "pdv_open_channel('%s', %d, %d)\n", dev_name ? dev_name : "NULL",
00465         unit, channel);
00466 
00467     if (dev_name == NULL)
00468         strcpy(tmpname, EDT_INTERFACE);
00469     else
00470         strcpy(tmpname, dev_name);
00471     if ((pdv_p = edt_open_channel(tmpname, unit, channel)) == NULL)
00472         return NULL;
00473 
00474 
00475     if (pdv_p->devid == PDVFOI_ID)
00476     {
00477 #ifdef _FOI_SUPPORTED
00478         edt_check_foi(pdv_p);
00479 #else
00480         edt_msg(PDVFATAL, "pdv_open_channel: FOI not supported after v4.1.5.9\n"); 
00481         return NULL;
00482 #endif
00483     }
00484     else 
00485     {
00486         pdv_p->foi_unit = channel;
00487     }
00488 
00489     /*
00490     * alloc and get the PCI DV dependent methods struct, which should have
00491     * been initialized in the driver by initcam.
00492     */
00493     if (sizeof(Dependent) > EDT_DEPSIZE)
00494     {
00495         edt_msg(PDVWARN, "pdv_open_channel: sizeof Dependent %d > DEPSIZE %d\n",
00496             sizeof(Dependent), EDT_DEPSIZE);
00497     }
00498     if ((dd_p = (Dependent *) malloc(EDT_DEPSIZE)) == NULL)
00499     {
00500         pdv_close(pdv_p);
00501         return NULL;
00502     }
00503     pdv_p->dd_p = dd_p;
00504 
00505     if (edt_get_dependent(pdv_p, dd_p) < 0)
00506     {
00507         free(dd_p);
00508         dd_p = 0;
00509         pdv_p->dd_p = NULL;
00510         pdv_close(pdv_p);
00511         return NULL;
00512     }
00513 
00514     if (pdv_p->devid == PDVFOI_ID)
00515     {
00516         pdv_p->foi_unit = edt_get_foiunit(pdv_p);
00517     }
00518 
00519     pdv_p->tmpbufsize = 0;
00520 
00521     pdv_p->dd_p->xilinx_rev = 2;
00522 
00523     if (pdv_p->dd_p->swinterlace ||
00524         pdv_p->dd_p->interlace_module[0])
00525         pdv_setup_postproc(pdv_p, pdv_p->dd_p, NULL);
00526 
00527     return pdv_p;
00528 
00529 }
00530 
00531 
00532 
00559 PdvDev *
00560 pdv_open(char *dev_name, int unit)
00561 {
00562     return pdv_open_channel(dev_name, unit, 0);
00563 }
00564 
00565 
00572 void
00573 pdv_setup_dma(PdvDev * pdv_p)
00574 
00575 {
00576     /* This looks like bad stuff to put in the open function... */
00577     /* Since we might not always want to affect */
00578 
00579     edt_set_continuous(pdv_p, 0);
00580     pdv_p->dd_p->started_continuous = 0;
00581 
00582     edt_startdma_reg(pdv_p, PDV_CMD, PDV_ENABLE_GRAB);
00583 }
00584 
00585 
00586 
00595 int
00596 pdv_close(PdvDev * pdv_p)
00597 {
00598     edt_msg(DBG2, "pdv_close()\n");
00599 
00600     if (!pdv_p)
00601         return -1;
00602     if (pdv_p->dd_p)
00603     {
00604         free(pdv_p->dd_p);
00605         pdv_p->dd_p = 0;
00606     }
00607 
00608     return edt_close(pdv_p);
00609 }
00610 
00620 int
00621 pdv_bytes_per_line(int width, int depth)
00622 
00623 {
00624     if (depth == 1)
00625         return width >> 3;
00626     else if (depth == 2)
00627         return width >> 2;
00628     else if (depth == 4)
00629         return width >> 1;
00630     else
00631         return width * bits2bytes(depth);
00632 }
00633 
00640 int
00641 pdv_get_bytes_per_image(PdvDev *pdv_p)
00642 
00643 {
00644     return pdv_p->dd_p->height * 
00645         pdv_bytes_per_line(pdv_p->dd_p->width, pdv_p->dd_p->depth);
00646 }
00647 
00648 
00663 int
00664 pdv_get_width(PdvDev * pdv_p)
00665 {
00666     if (!pdv_p->dd_p)
00667         return (0);
00668 
00669     edt_msg(DBG2, "pdv_get_width() %d\n", pdv_p->dd_p->width);
00670 
00671 
00672     return pdv_p->dd_p->width;
00673 }
00674 
00683 int
00684 pdv_get_pitch(PdvDev * pdv_p)
00685 {
00686     int pitch;
00687 
00688     if (!pdv_p->dd_p)
00689         return (0);
00690 
00691     pitch = pdv_bytes_per_line(pdv_p->dd_p->width, 
00692         pdv_p->dd_p->depth);
00693 
00694     edt_msg(DBG2, "pdv_get_pitch() %d\n", pitch);
00695 
00696 
00697     return pitch ;
00698 }
00699 
00720 int
00721 pdv_get_cam_width(PdvDev * pdv_p)
00722 {
00723     edt_msg(DBG2, "pdv_get_cam_width() %d\n", pdv_p->dd_p->cam_width);
00724 
00725     return pdv_p->dd_p->cam_width;
00726 }
00727 
00743 int
00744 pdv_get_dmasize(PdvDev * pdv_p)
00745 
00746 {
00747 
00748     Dependent *dd_p = PDV_DEPENDENT(pdv_p);
00749 
00750     int     size;
00751     int     extra_dma = 0;
00752 
00753     /* NEW header_within allocates extra buffer AND DMA the size of header_size */
00754     if (pdv_p->dd_p->header_position == HeaderBegin ||
00755         pdv_p->dd_p->header_position == HeaderMiddle ||
00756         pdv_p->dd_p->header_position == HeaderEnd)
00757         extra_dma = pdv_p->dd_p->header_size;
00758 
00759     if (dd_p->swinterlace == PDV_INV_RT_INTLV_24_12)
00760         size = dd_p->width * dd_p->height * 3 / 2;
00761     else if (dd_p->depth > dd_p->extdepth) /* 24 bit bayer filter  or 1 bit data*/
00762         size = dd_p->height * 
00763         pdv_bytes_per_line(pdv_p->dd_p->width, pdv_p->dd_p->extdepth);
00764     else
00765         size = dd_p->height * 
00766         pdv_bytes_per_line(pdv_p->dd_p->width, pdv_p->dd_p->depth);
00767 
00768     return size + extra_dma;
00769 }
00770 
00787 int
00788 pdv_setsize(PdvDev * pdv_p, int width, int height)
00789 {
00790     Dependent *dd_p = pdv_p->dd_p;
00791 
00792     edt_msg(DBG2, "pdv_setsize(%d, %d)\n", width, height);
00793 
00794     dd_p->width = width;
00795     dd_p->height = height;
00796 
00797     return pdv_update_size(pdv_p);
00798 
00799 }
00800 
00820 int
00821 pdv_set_cam_width(PdvDev * pdv_p, int value)
00822 {
00823     int     ret;
00824     Dependent *dd_p = pdv_p->dd_p;
00825 
00826     edt_msg(DBG2, "pdv_set_cam_width(%d)\n", value);
00827 
00828     dd_p->cam_width = value;
00829 
00830     ret = edt_set_dependent(pdv_p, dd_p);
00831 
00832     return ret;
00833 }
00834 
00845 int
00846 pdv_get_imagesize(PdvDev * pdv_p)
00847 {
00848 
00849     edt_msg(DBG2, "pdv_get_imagesize() %d\n", pdv_p->dd_p->imagesize);
00850 
00851     return pdv_p->dd_p->imagesize;
00852 }
00853 
00862 int
00863 pdv_get_allocated_size(PdvDev * pdv_p)
00864 {
00865     Dependent *dd_p = pdv_p->dd_p;
00866     int     total = 0;
00867 
00868     dd_p->imagesize = dd_p->width * dd_p->height * bits2bytes(dd_p->depth);
00869 
00870     total = pdv_p->dd_p->imagesize + pdv_p->dd_p->slop + pdv_p->dd_p->header_size;
00871 
00872 #ifdef _NT_
00873 
00874     if (total % PAGESIZE)
00875     {
00876         total = ((total / PAGESIZE) + 1) * PAGESIZE;
00877     }
00878 #endif
00879 
00880     edt_msg(DBG2, "pdv_get_allocated_size() %d\n", total);
00881 
00882     return total;
00883 
00884 }
00885 
00905 int
00906 pdv_set_timeout(PdvDev * pdv_p, int value)
00907 {
00908     Dependent *dd_p = pdv_p->dd_p;
00909 
00910     if (value < 0)
00911     {
00912         edt_msg(DBG2, "pdv_set_timeout(%d) (< 0, going back to auto)\n", value);
00913 
00914         pdv_p->dd_p->user_timeout_set = 0;
00915         edt_set_dependent(pdv_p, dd_p);
00916         return pdv_auto_set_timeout(pdv_p);
00917     }
00918     else
00919     {
00920         edt_msg(DBG2, "pdv_set_timeout(%d) (user set, overriding auto)\n", value);
00921 
00922         pdv_p->dd_p->user_timeout_set = 1;
00923         pdv_p->dd_p->user_timeout = value;
00924         edt_set_dependent(pdv_p, dd_p);
00925         return edt_set_rtimeout(pdv_p, value);
00926     }
00927 }
00928 
00943 int
00944 pdv_get_timeout(PdvDev * pdv_p)
00945 {
00946 
00947     edt_msg(DBG2, "pdv_get_timeout()\n");
00948 
00949     return edt_get_rtimeout(pdv_p);
00950 }
00951 
00964 int
00965 pdv_picture_timeout(PdvDev * pdv_p, int value)
00966 {
00967     return pdv_set_timeout(pdv_p, value);
00968 }
00969  /* end settings */
00971 
00972 
01011 int
01012 pdv_timeouts(PdvDev * pdv_p)
01013 {
01014     int     ret;
01015 
01016     ret = edt_timeouts(pdv_p);
01017     edt_msg(DBG2, "pdv_timeouts(%d)\n", ret);
01018     return ret;
01019 }
01020 
01021 
01034 int
01035 pdv_timeout_cleanup(PdvDev * pdv_p)
01036 {
01037     int     curdone, curtodo;
01038 
01039     curdone = edt_done_count(pdv_p);
01040     curtodo = edt_get_todo(pdv_p);
01041     pdv_stop_continuous(pdv_p);
01042     edt_msleep(500);
01043     edt_set_buffer(pdv_p, curdone);
01044     edt_reg_write(pdv_p, PDV_CMD, PDV_RESET_INTFC);
01045     pdv_setup_continuous(pdv_p);
01046     return curtodo - curdone;
01047 }
01048  /* end acquisition */
01050 
01051 
01069 int
01070 pdv_get_height(PdvDev * pdv_p)
01071 {
01072     if (!pdv_p->dd_p)
01073         return (0);
01074 
01075     edt_msg(DBG2, "pdv_get_height() %d\n", pdv_p->dd_p->height);
01076 
01077     return pdv_p->dd_p->height;
01078 }
01079 
01099 int
01100 pdv_get_cam_height(PdvDev * pdv_p)
01101 {
01102 
01103     edt_msg(DBG2, "pdv_get_cam_height() %d\n", pdv_p->dd_p->cam_height);
01104 
01105     return pdv_p->dd_p->cam_height;
01106 }
01107 
01108 
01125 int
01126 pdv_get_frame_height(PdvDev * pdv_p)
01127 {
01128 
01129     edt_msg(DBG2, "pdv_get_cam_height() %d\n", pdv_p->dd_p->cam_height);
01130 
01131     return pdv_p->dd_p->frame_height;
01132 }
01133  /* end settings */
01135 
01145 int
01146 pdv_update_size(PdvDev *pdv_p)
01147 
01148 {
01149     Dependent *dd_p = pdv_p->dd_p;
01150     int ret;
01151 
01152     edt_msg(DBG2, "update_size\n");
01153 
01154     dd_p->imagesize = dd_p->height * pdv_get_pitch(pdv_p);
01155 
01156     ret = edt_set_dependent(pdv_p, dd_p);
01157 
01158     if (pdv_p->ring_buffer_numbufs > 0)
01159         pdv_multibuf(pdv_p, pdv_p->ring_buffer_numbufs);
01160 
01161     if (dd_p->swinterlace)
01162     {
01163         pdv_alloc_tmpbuf(pdv_p);
01164     }
01165 
01166     return ret;
01167 }
01168 
01180 int
01181 pdv_set_width(PdvDev * pdv_p, int value)
01182 {
01183     Dependent *dd_p = pdv_p->dd_p;
01184 
01185     edt_msg(DBG2, "pdv_set_width(%d)\n", value);
01186 
01187     dd_p->width = value;
01188 
01189     return pdv_update_size(pdv_p);
01190 
01191 }
01192 
01201 int
01202 pdv_set_height(PdvDev * pdv_p, int value)
01203 {
01204     Dependent *dd_p = pdv_p->dd_p;
01205 
01206     edt_msg(DBG2, "pdv_set_height(%d)\n", value);
01207 
01208     dd_p->height = value;
01209 
01210     return pdv_update_size(pdv_p);
01211 
01212 }
01213 
01231 int
01232 pdv_set_cam_height(PdvDev * pdv_p, int value)
01233 {
01234     int     ret;
01235     Dependent *dd_p = pdv_p->dd_p;
01236 
01237     edt_msg(DBG2, "pdv_set_cam_height(%d)\n", value);
01238 
01239     dd_p->cam_height = value;
01240 
01241     ret = edt_set_dependent(pdv_p, dd_p);
01242     return ret;
01243 }
01244 
01245 
01254 int
01255 pdv_get_depth(PdvDev * pdv_p)
01256 {
01257     if (!pdv_p->dd_p)
01258         return (0);
01259 
01260     edt_msg(DBG2, "pdv_get_depth() %d\n", pdv_p->dd_p->depth);
01261 
01262     return pdv_p->dd_p->depth;
01263 }
01264 
01282 int
01283 pdv_get_extdepth(PdvDev * pdv_p)
01284 {
01285 
01286     edt_msg(DBG2, "pdv_get_extdepth() %d\n", pdv_p->dd_p->extdepth);
01287 
01288     return pdv_p->dd_p->extdepth;
01289 }
01290 
01316 int
01317 pdv_set_depth(PdvDev * pdv_p, int value)
01318 {
01319     Dependent *dd_p = pdv_p->dd_p;
01320 
01321     dd_p->depth = value;
01322 
01323     /* set cameralink data path register, if appropriate -- note that
01324     * odball values are generally  handled differently (e.g.
01325     * pdvcamlk_pir which has hard-coded depth)
01326     */
01327     if (pdv_is_cameralink(pdv_p))
01328     {
01329         int reg;
01330 
01331         if ((value >= 8) && (value <= 16))
01332             reg = value-1;
01333         else if (value == 24 || value == 32)
01334             reg = 0x7;
01335         else if (value == 30)
01336             reg = 0x9;
01337         else reg = 0;
01338 
01339         if (reg)
01340         {
01341             if (dd_p->dual_channel)
01342                 reg |= 0x10;
01343             dd_p->dual_channel = reg;
01344             edt_reg_write(pdv_p, PDV_CL_DATA_PATH, dd_p->cl_data_path);
01345         }
01346     }
01347 
01348     return pdv_update_size(pdv_p);
01349 
01350 }
01351 
01376 int
01377 pdv_set_extdepth(PdvDev * pdv_p, int value)
01378 {
01379     int     ret;
01380     Dependent *dd_p = pdv_p->dd_p;
01381 
01382     dd_p->extdepth = value;
01383 
01384     edt_msg(DBG2, "pdv_set_extdepth(%d)\n", value);
01385 
01386     ret = edt_set_dependent(pdv_p, dd_p);
01387 
01388     return ret;
01389 }
01390 
01402 int
01403 pdv_set_cameratype(PdvDev * pdv_p, char *model)
01404 {
01405     Dependent *dd_p = pdv_p->dd_p;
01406 
01407     edt_msg(DBG2, "pdv_set_cameratype(%s)\n", model);
01408 
01409     strcpy(dd_p->cameratype, model);
01410 
01411     return edt_set_dependent(pdv_p, dd_p);
01412 }
01413 
01414 
01431 char   *
01432 pdv_get_cameratype(PdvDev * pdv_p)
01433 {
01434     edt_msg(DBG2, "pdv_get_cameratype()\n");
01435 
01436     return pdv_p->dd_p->cameratype;
01437 }
01438 
01439 
01456 char   *
01457 pdv_get_camera_class(PdvDev * pdv_p)
01458 {
01459     edt_msg(DBG2, "pdv_get_camera_class()\n");
01460 
01461     return pdv_p->dd_p->camera_class;
01462 }
01463 
01464 
01474 char   *
01475 pdv_get_camera_model(PdvDev * pdv_p)
01476 {
01477     edt_msg(DBG2, "pdv_get_camera_model()\n");
01478 
01479     return pdv_p->dd_p->camera_model;
01480 }
01481 
01492 char   *
01493 pdv_get_camera_info(PdvDev * pdv_p)
01494 {
01495     edt_msg(DBG2, "pdv_get_camera_info()\n");
01496 
01497     return pdv_p->dd_p->camera_info;
01498 }
01499 
01511 char   *
01512 pdv_camera_type(PdvDev * pdv_p)
01513 {
01514     edt_msg(DBG2, "pdv_camera_type()\n");
01515 
01516     return pdv_p->dd_p->cameratype;
01517 }
01518  /* end settings */
01520 
01521 static int
01522 smd_read_reg(PdvDev * pdv_p, int reg)
01523 {
01524     u_char  buf[128];
01525     int     ret;
01526 
01527     /* flush out any junk */
01528     pdv_serial_read(pdv_p, (char *) buf, 64);
01529 
01530     /* read SMD frame rate register */
01531     buf[0] = (u_char) reg;
01532     pdv_serial_binary_command(pdv_p, (char *) buf, 1);
01533 
01534     ret = pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, pdv_p->dd_p->serial_respcnt);
01535     if (ret == 0)
01536         return -1;
01537     pdv_serial_read(pdv_p, (char *) buf, ret);
01538     return (int) buf[0];
01539 }
01540 
01541 /*
01542  * for serial_format new as of 4.2.3.2 -- allow serial_exposure/gain/blacklevel
01543  * to be a %x or %d or some such, e.g. EXP %d or SM=%02x. Note: Up to 4 % expressions
01544  * can be present but the same value will be entered for each
01545  * ONE % expression. Allow \% to go through 
01546  * RETURNS:  number of % expressions, or -1 if invalid format
01547  */
01548 static int
01549 check_valid_formatstr(char *str)
01550 {
01551     int i, len = strlen(str);
01552     int ret = 0;
01553 
01554     for (i=0; i<len; i++)
01555     {
01556         if (str[i] == '%')
01557         {
01558             if ((i > 0) && (str[i-1] != '\\')) /* escaped so never mind */
01559                 ++ret;
01560             else if (i == len-1) /* % can't be the last character unless escaped */
01561             {
01562                 ret = -1;
01563                 break;
01564             }
01565             /* ALERT should be more checks here, for valid formatting */
01566         }
01567     }
01568     return ret;
01569 }
01570 
01601 int
01602 pdv_set_exposure(PdvDev * pdv_p, int value)
01603 {
01604     int     ret = -1;
01605     Dependent *dd_p = pdv_p->dd_p;
01606     char    cmdstr[64];
01607     int     n;
01608 
01609     cmdstr[0] = '\0';
01610 
01611     edt_msg(DBG2, "pdv_set_exposure(%d)\n", value);
01612 
01613     dd_p->shutter_speed = value;
01614 
01615     if (edt_set_dependent(pdv_p, dd_p) < 0)
01616     {
01617         edt_msg(DBG2, "pdv_set_exposure ret %d\n", ret);
01618         return -1;
01619     }
01620 
01621     pdv_auto_set_timeout(pdv_p);
01622 
01623     if ((dd_p->camera_shutter_timing == AIA_MCL)
01624         && (dd_p->mode_cntl_norm & 0xf0)
01625         && (!dd_p->trig_pulse))
01626     {
01627         ret = pdv_set_exposure_mcl(pdv_p, value);
01628     }
01629     else if (dd_p->camera_shutter_timing == AIA_MCL_100US)
01630     {
01631         /* in this case do mcl even if trig_pulse */
01632         ret = pdv_set_exposure_mcl(pdv_p, value);
01633     }
01634     else if ((strlen(dd_p->serial_exposure) >= 0) && (dd_p->serial_format == SERIAL_BINARY))
01635     {
01636         send_serial_binary_cmd(pdv_p, dd_p->serial_exposure, value);
01637     }
01638     else if ((strlen(dd_p->serial_exposure) >= 0)
01639              && ((dd_p->serial_format == SERIAL_ASCII)
01640                  || (dd_p->serial_format == SERIAL_ASCII_HEX)
01641                  || (dd_p->serial_format == SERIAL_PULNIX_1010)))
01642     {
01643         /* special serial cmd for ham 4880 */
01644         /* ALERT: get rid of this, s/b camera_shutter_timing here and */
01645         /* in config files and everywhere else....! */
01646         if (dd_p->camera_shutter_timing == HAM_4880_SER)
01647         {
01648             int     minutes;
01649             int     seconds;
01650             int     useconds;
01651 
01652             minutes = value / 60000;
01653             value -= minutes * 60000;
01654 
01655             seconds = value / 1000;
01656             value -= seconds * 1000;
01657 
01658             useconds = value;
01659 
01660             sprintf(cmdstr, "%s %04d:%02d.%03d",
01661                     dd_p->serial_exposure, minutes, seconds, useconds);
01662         }
01663 
01664         else switch(dd_p->serial_format)
01665         {
01666 
01667             case SERIAL_ASCII_HEX:
01668                 sprintf(cmdstr, "%s %02x", dd_p->serial_exposure, value);
01669                 break;
01670 
01671             case SERIAL_PULNIX_1010:
01672                 sprintf(cmdstr, "%s%d", dd_p->serial_exposure, value);
01673                 break;
01674 
01675             case SERIAL_ASCII:
01676             default:
01677             {
01678                 int n = check_valid_formatstr(dd_p->serial_offset); 
01679 
01680                 cmdstr[0] = '\0';
01681 
01682                 if (n == 0) /* no % formatting, use old method */
01683                     sprintf(cmdstr, "%s %d", dd_p->serial_offset, value);
01684                 else if ((n > 0) && (n < 5))
01685                     sprintf(cmdstr, dd_p->serial_offset, value, value, value, value);
01686 
01687                 if (cmdstr[0])
01688                 {
01689                     ret = pdv_serial_command_flagged(pdv_p, cmdstr, SCFLAG_NORESP);
01690 
01691                     pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, 64);
01692                     if (*pdv_p->dd_p->serial_response)
01693                         pdv_serial_read(pdv_p, cmdstr, 63);
01694                 }
01695             }
01696 
01697                 if (check_valid_formatstr(dd_p->serial_exposure) >= 1)
01698                     sprintf(cmdstr, dd_p->serial_exposure, value, value, value, value);
01699                 else sprintf(cmdstr, "%s %d", dd_p->serial_exposure, value);
01700                 break;
01701         }
01702 
01703         if (cmdstr[0])
01704         {
01705             ret = pdv_serial_command_flagged(pdv_p, cmdstr, SCFLAG_NORESP);
01706             n = pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, pdv_p->dd_p->serial_respcnt);
01707             if (*pdv_p->dd_p->serial_response)
01708                 if (n)
01709                     pdv_serial_read(pdv_p, cmdstr, n);
01710         }
01711     }
01712     else if ((dd_p->camera_shutter_timing == SPECINST_SERIAL)
01713         || (dd_p->camera_shutter_speed == SPECINST_SERIAL))
01714     {
01715         ret = pdv_set_exposure_specinst(pdv_p, value);
01716     }
01717     else if (dd_p->camera_shutter_timing == SMD_SERIAL)
01718     {
01719         ret = pdv_set_exposure_smd(pdv_p, value);
01720     }
01721     else if (dd_p->camera_shutter_timing == PTM6710_SERIAL)
01722     {
01723         ret = pdv_set_exposure_ptm6710_1020(pdv_p, value);
01724     }
01725     else if (dd_p->camera_shutter_timing == TOSHIBA_SERIAL)
01726     {
01727         ret = pdv_set_exposure_toshiba(pdv_p, value);
01728     }
01729     else if (dd_p->camera_shutter_timing == COHU_SERIAL)
01730     {
01731         ret = pdv_set_exposure_cohu(pdv_p, value);
01732     }
01733     else if (dd_p->camera_shutter_timing == PTM1020_SERIAL)
01734     {
01735         ret = pdv_set_exposure_ptm6710_1020(pdv_p, value);
01736     }
01737     else if (dd_p->camera_shutter_timing == TIMC1001_SERIAL)
01738     {
01739         ret = pdv_set_exposure_timc1001pf(pdv_p, value);
01740     }
01741     else if (dd_p->camera_shutter_timing == ADIMEC_SERIAL)
01742     {
01743         ret = pdv_set_exposure_adimec(pdv_p, value);
01744     }
01745     else if (dd_p->camera_shutter_timing == BASLER202K_SERIAL)
01746     {
01747         ret = pdv_set_exposure_basler202k(pdv_p, value);
01748     }
01749     else if (dd_p->camera_shutter_timing == SU320_SERIAL)
01750     {
01751         ret = pdv_set_exposure_su320(pdv_p, value);
01752     }
01753     else if (dd_p->camera_shutter_timing == HAM_4880_SER)
01754     {
01755         /* controlled by serial; do nothing */
01756     }
01757     else if (dd_p->camera_shutter_timing == AIA_SERIAL)
01758     {
01759         /* controlled by serial; do nothing */
01760     }
01761     else if (dd_p->camera_shutter_timing == AIA_SERIAL_ES40)
01762     {
01763         /* controlled by serial; do nothing */
01764     }
01765     else if (dd_p->camera_shutter_timing == AIA_TRIG)
01766     {
01767         ret = pdv_set_exposure_mcl(pdv_p, value);
01768     }
01769     else if (!dd_p->trig_pulse)
01770     {
01771         /* default to aia mcl if not trig_pulse */
01772         ret = pdv_set_exposure_mcl(pdv_p, value);
01773     }
01774 
01775     edt_msg(DBG2, "pdv_set_exposure returns %d\n", ret);
01776     return (ret);
01777 }
01778 
01795 int
01796 pdv_set_exposure_mcl(PdvDev * pdv_p, int value)
01797 {
01798     u_int   data_path;
01799 
01800     if (value < 0)
01801         value = 0;
01802     if (value > 25500)
01803         value = 25500;
01804 
01805     pdv_p->dd_p->shutter_speed = value;
01806 
01807     data_path = pdv_p->dd_p->datapath_reg;
01808     data_path &= ~PDV_MULTIPLIER_MASK;
01809 
01810 
01811     /*
01812     * special case microsecond shutter timer
01813     */
01814     if (pdv_p->dd_p->camera_shutter_timing == AIA_MCL_100US)
01815     {
01816         edt_msg(DBG2, "pdv_set_exposure_mcl(%d) (100US)\n", value);
01817 
01818         if (value < 256)
01819         {
01820             data_path |= PDV_MULTIPLIER_100US;
01821         }
01822         else if (value < 2560)
01823         {
01824             /* already turned off multiplier */
01825             value = (value + 5) / 10;
01826         }
01827         else if (value < 25600)
01828         {
01829             data_path |= PDV_MULTIPLIER_10MS;
01830             value = (value + 50) / 100;
01831         }
01832         else if (value < 256000)
01833         {
01834             data_path |= PDV_MULTIPLIER_100MS;
01835             value = (value + 50) / 1000;
01836         }
01837     }
01838     else
01839     {
01840         edt_msg(DBG2, "pdv_set_exposure_mcl(%d)\n", value);
01841 
01842         if (value < 256)
01843         {
01844             /* already turned off multiplier */
01845         }
01846         else if (value < 2560)
01847         {
01848             data_path |= PDV_MULTIPLIER_10MS;
01849             value = (value + 5) / 10;
01850         }
01851         else
01852         {
01853             data_path |= PDV_MULTIPLIER_100MS;
01854             value = (value + 50) / 100;
01855         }
01856     }
01857 
01858     pdv_p->dd_p->datapath_reg = data_path;
01859     edt_reg_write(pdv_p, PDV_SHUTTER, value);
01860     edt_reg_write(pdv_p, PDV_DATA_PATH, data_path);
01861 
01862     return 0;
01863 }
01864 
01868 static int
01869 pdv_set_exposure_smd(PdvDev * pdv_p, int value)
01870 {
01871     int     fp = 0;
01872     u_char  buf[128];
01873     int     n;
01874     int     ret = 0;
01875     int     smd_reg1, smd_reg3;
01876 
01877 
01878     if (Smd_type == NOT_SET)
01879     {
01880         Smd_type = smd_read_reg(pdv_p, SMD_READ_CAMTYPE);
01881         if ((Smd_type & 0xfff) == 0xfff)        /* sometimes there's garbage
01882                                                 * at first; if so try again */
01883                                                 Smd_type = smd_read_reg(pdv_p, SMD_READ_CAMTYPE);
01884     }
01885 
01886     /* send SMD write integration reg. command and arg */
01887     switch (Smd_type)
01888     {
01889     case SMD_TYPE_4M4:
01890         /*
01891         * set time to send, then write that based on msecs (value is int so
01892         * can't do 0.5msec, just use 0 for that -- $#^&*@ screwy way to do
01893         * it if you ask me.....) buf[0] = (u_char) SMD_4M4_WRITE_R2;
01894         */
01895         if (value == 0)         /* 500us */
01896             buf[1] = 0x7d;
01897         else if (value == 1)    /* 1ms */
01898             buf[1] = 0x7b;
01899         else if (value == 2)    /* 2ms */
01900             buf[1] = 0x77;
01901         else if (value <= 4)    /* 4ms */
01902             buf[1] = 0x6f;
01903         else if (value <= 8)    /* 8ms */
01904             buf[1] = 0x5f;
01905         else if (value <= 16)   /* 16ms */
01906             buf[1] = 0x3f;
01907         else                    /* 32ms (default) */
01908             buf[1] = 0x00;
01909         /*
01910         * send write r2 (integration reg) command
01911         */
01912         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
01913         break;
01914 
01915     case SMD_TYPE_BT25:
01916         /*
01917         * adjust timeout multiplier according to frame rate
01918         */
01919         buf[0] = (u_char) SMD_BT25_WRITE_R2;
01920         if (Smd_rate == NOT_SET)
01921         {
01922             if ((Smd_rate = smd_read_reg(pdv_p, SMD_BT25_READ_FRAMERATE)) == -1)
01923                 edt_msg(PDVWARN, "libpdv: no response from SMD camera rate reg read\n");
01924             if (pdv_p->dd_p->timeout_multiplier < Smd_rate)
01925             {
01926                 pdv_p->dd_p->timeout_multiplier = Smd_rate;
01927                 pdv_auto_set_timeout(pdv_p);
01928             }
01929         }
01930         buf[1] = (u_char) value;
01931         /*
01932         * send write r2 (integration reg) command
01933         */
01934         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
01935 
01936         /* SMD doesn't resp but do a dummy wait to make sure its done */
01937         pdv_serial_wait(pdv_p, 100, 64);
01938         break;
01939 
01940     case SMD_TYPE_1M30P:
01941     case SMD_TYPE_6M3P:
01942         buf[0] = (u_char) SMD_1M30P_REG_W_INTEG0;
01943         buf[1] = value & 0xff;
01944         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
01945 
01946         buf[0] = (u_char) SMD_1M30P_REG_W_INTEG1;
01947         buf[1] = (value & 0xff00) >> 8;
01948         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
01949 
01950         buf[0] = (u_char) SMD_1M30P_REG_W_INTEG2;
01951         buf[1] = (value & 0xff0000) >> 16;
01952         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
01953 
01954         /*
01955         * SMD 1M30p  shutter speeds are in uSecs, so fake out
01956         * pdv_auto_set_timeout, then switch speed back to actual value
01957         */
01958         /*
01959         * ALERT: should take frame rate (& binning?) into account here too
01960         */
01961         pdv_p->dd_p->shutter_speed = value / 1000;
01962         pdv_auto_set_timeout(pdv_p);
01963         pdv_p->dd_p->shutter_speed = value;
01964         break;
01965 
01966     case SMD_TYPE_1M15P:
01967         if ((smd_reg1 = smd_read_reg(pdv_p, SMD_1M15P_READ_R1)) == -1)
01968         {
01969             edt_msg(PDVWARN, "libpdv: no response from SMD R1 reg read\n");
01970             return -1;
01971         }
01972 
01973 
01974         buf[0] = (u_char) SMD_1M15P_WRITE_R1;
01975 
01976         /*
01977         * valid values for this camera are 0, 1, 2, 4 and 8, but allow values
01978         * in between and just round down 
01979         */
01980         if (value == 0)
01981         {
01982             buf[1] = (smd_reg1 &~ SMD_1M15P_R1_INTMSK) | 0x0; /* NONE */
01983             fp = 65000;
01984         }
01985         else if (value == 1)
01986         {
01987             buf[1] = (smd_reg1 &~ SMD_1M15P_R1_INTMSK) | 0x7; /* 1 ms */
01988             fp = 65000;
01989         }
01990         else if (value < 4)
01991         {
01992             buf[1] = (smd_reg1 &~ SMD_1M15P_R1_INTMSK) | 0x6; /* 2 ms */
01993             fp = 64000;
01994         }
01995         else if (value < 7)
01996         {
01997             buf[1] = (smd_reg1 &~ SMD_1M15P_R1_INTMSK) | 0x5; /* 4 ms */
01998             fp = 62000;
01999         }
02000         else if (value == 8)
02001         {
02002             buf[1] = (smd_reg1 &~ SMD_1M15P_R1_INTMSK) | 0x4; /* 8 ms */
02003             fp = 58000;
02004         }
02005         else return -1;
02006 
02007         if (smd_reg1 & SMD_1M15P_R1_TRIGMODE)
02008         {
02009             /* if binned and triggered, use half the frame delay */ 
02010             smd_reg3 = smd_read_reg(pdv_p, SMD_1M15P_READ_R3);
02011             if (smd_reg3 & 0x40) /* 2x2 bin mode bit */
02012                 fp /= 2;
02013             pdv_set_frame_period(pdv_p, fp, PDV_FVAL_ADJUST);
02014         }
02015 
02016         pdv_p->dd_p->shutter_speed = value;
02017         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
02018         break;
02019 
02020     default:
02021         ret = -1;
02022         edt_msg(PDVWARN, "libpdv: unknown SMD camera type %02x\n", Smd_type);
02023         break;
02024     }
02025 
02026     if (!ret)
02027     {
02028         /* SMD doesn't respond but do a dummy wait to make sure its done */
02029         n = pdv_serial_wait(pdv_p, 100, 64);
02030         if (n > 127)
02031             n = 127;
02032         if (n)
02033             pdv_serial_read(pdv_p, (char *) buf, n);
02034     }
02035     return ret;
02036 }
02037 
02046 static int
02047 pdv_set_exposure_timc1001pf(PdvDev * pdv_p, int value)
02048 {
02049     Dependent *dd_p = pdv_p->dd_p;
02050     u_int   mcl = edt_reg_read(pdv_p, PDV_MODE_CNTL) & 0xf1;
02051 
02052     if ((value >= 0) && (value <= 7))
02053     {
02054         dd_p->shutter_speed = value;
02055         mcl |= (value << 1);
02056         edt_reg_write(pdv_p, PDV_MODE_CNTL, mcl);
02057         return 0;
02058     }
02059     return -1;
02060 }
02061 
02065 static int
02066 pdv_set_exposure_toshiba(PdvDev * pdv_p, int value)
02067 {
02068     char    cmdbuf[128];
02069     int n;
02070 
02071     if ((value < 0) || (value > 0xff))
02072         return -1;
02073 
02074     cmdbuf[0] = 0x02;
02075     sprintf(cmdbuf+1, "68%02X", value);
02076     cmdbuf[5] = 0x03;
02077     pdv_serial_binary_command(pdv_p, (char *)cmdbuf, 6);
02078 
02079     /* response should be <STX><ACK><ETX> */
02080     if (n = pdv_serial_wait(pdv_p, 200, 3))
02081         pdv_serial_read(pdv_p, cmdbuf, n);
02082 
02083     cmdbuf[0] = 0x02;
02084     sprintf(cmdbuf+1, "6E01");
02085     cmdbuf[5] = 0x03;
02086     pdv_serial_binary_command(pdv_p, (char *)cmdbuf, 6);
02087 
02088     /* response should be <STX><ACK><ETX> */
02089     if (n = pdv_serial_wait(pdv_p, 200, 3))
02090         pdv_serial_read(pdv_p, cmdbuf, n);
02091 
02092     return 0;
02093 }
02094 
02098 static int
02099 pdv_set_gain_toshiba(PdvDev * pdv_p, int value)
02100 {
02101     char    cmdbuf[128];
02102     int n;
02103 
02104     if ((value < 0) || (value > 0xff))
02105         return -1;
02106 
02107     cmdbuf[0] = 0x02;
02108     sprintf(cmdbuf+1, "64%02X", value);
02109     cmdbuf[5] = 0x03;
02110     pdv_serial_binary_command(pdv_p, (char *)cmdbuf, 6);
02111 
02112     /* response should be <STX><ACK><ETX> */
02113     if (n = pdv_serial_wait(pdv_p, 200, 3))
02114         pdv_serial_read(pdv_p, cmdbuf, n);
02115 
02116     cmdbuf[0] = 0x02;
02117     sprintf(cmdbuf+1, "6E01");
02118     cmdbuf[5] = 0x03;
02119     pdv_serial_binary_command(pdv_p, (char *)cmdbuf, 6);
02120 
02121     /* response should be <STX><ACK><ETX> */
02122     if (n = pdv_serial_wait(pdv_p, 200, 3))
02123         pdv_serial_read(pdv_p, cmdbuf, n);
02124 
02125     return 0;
02126 }
02127 
02131 static int
02132 pdv_set_exposure_cohu(PdvDev * pdv_p, int value)
02133 {
02134     char    cmdbuf[128];
02135     int n, len;
02136 
02137     if ((value < 0) || (value > 10))
02138         return -1;
02139 
02140     /* send STX ID 'c' 'E' value 81 ETX (value is ASCII int, 81 is dummy checksum) */
02141     cmdbuf[0] = 0x02; /* STX */
02142     cmdbuf[1] = 0x01; /* Camera ID 1 */
02143     sprintf(cmdbuf+2, "cE2,%d", value);
02144     len = strlen(cmdbuf);
02145     cmdbuf[len++] = (char)0x81;
02146     cmdbuf[len++] = (char)0x03;
02147     cmdbuf[len] = 0;
02148     pdv_serial_binary_command(pdv_p, (char *)cmdbuf, len);
02149 
02150     /* ALERT: check for specific response [ STX ID 'c' 'C' '0' CS ETX ] here? */
02151     if (n = pdv_serial_wait(pdv_p, 200, 7))
02152         pdv_serial_read(pdv_p, cmdbuf, n);
02153 
02154     /* send STX 'c' 'T' '0' 81 ETX (required to "make it so") */
02155     cmdbuf[0] = (char)0x02; /* STX */
02156     cmdbuf[1] = (char)0x01; /* Camera ID 1 */
02157     cmdbuf[2] = 'c';
02158     cmdbuf[3] = 'T';
02159     cmdbuf[4] = '0';
02160     cmdbuf[5] = (char)0x81;
02161     cmdbuf[6] = (char)0x03;
02162     pdv_serial_binary_command(pdv_p, (char *)cmdbuf, 7);
02163 
02164     /* ALERT: check for specific response [ STX ID 'c' 'C' '0' CS ETX ] here? */
02165     if (n = pdv_serial_wait(pdv_p, 200, 7))
02166         pdv_serial_read(pdv_p, cmdbuf, n);
02167 
02168     return 0;
02169 }
02170 
02174 static int
02175 pdv_set_gain_cohu(PdvDev * pdv_p, int value)
02176 {
02177     char    cmdbuf[128];
02178     int n, len;
02179 
02180     if ((value < 0) || (value > 320))
02181         return -1;
02182 
02183     /* send STX ID 'c' 'E' value 81 ETX (value is ASCII int, 81 is dummy checksum) */
02184     cmdbuf[0] = (char)0x02; /* STX */
02185     cmdbuf[1] = (char)0x01; /* Camera ID 1 */
02186     sprintf(cmdbuf+2, "cB1,%d", value);
02187     len = strlen(cmdbuf);
02188     cmdbuf[len++] = (char)0x81;
02189     cmdbuf[len++] = (char)0x03;
02190     cmdbuf[len] = 0;
02191     pdv_serial_binary_command(pdv_p, (char *)cmdbuf, len);
02192 
02193     /* ALERT: check for specific response [ STX ID 'c' 'C' '0' CS ETX ] here? */
02194     if (n = pdv_serial_wait(pdv_p, 200, 7))
02195         pdv_serial_read(pdv_p, cmdbuf, n);
02196 
02197     /* send STX 'c' 'T' '0' 81 ETX (required to "make it so") */
02198     cmdbuf[0] = (char)0x02; /* STX */
02199     cmdbuf[1] = (char)0x01; /* Camera ID 1 */
02200     cmdbuf[2] = 'c';
02201     cmdbuf[3] = 'T';
02202     cmdbuf[4] = '0';
02203     cmdbuf[5] = (char)0x81;
02204     cmdbuf[6] = (char)0x03;
02205     pdv_serial_binary_command(pdv_p, (char *)cmdbuf, 7);
02206 
02207     /* ALERT: check for specific response [ STX ID 'c' 'C' '0' CS ETX ] here? */
02208     if (n = pdv_serial_wait(pdv_p, 200, 7))
02209         pdv_serial_read(pdv_p, cmdbuf, n);
02210 
02211     return 0;
02212 }
02213 
02217 static int
02218 pdv_set_blacklevel_cohu(PdvDev * pdv_p, int value)
02219 {
02220     char    cmdbuf[128];
02221     int n, len;
02222 
02223     if ((value < 0) || (value > 1023))
02224         return -1;
02225 
02226     /* send STX ID 'c' 'E' value 81 ETX (value is ASCII int, 81 is dummy checksum) */
02227     cmdbuf[0] = 0x02; /* STX */
02228     cmdbuf[1] = 0x01; /* Camera ID 1 */
02229     sprintf(cmdbuf+2, "cB0,%d", value);
02230     len = strlen(cmdbuf);
02231     cmdbuf[len++] = (char)0x81;
02232     cmdbuf[len++] = (char)0x03;
02233     cmdbuf[len] = 0;
02234     pdv_serial_binary_command(pdv_p, (char *)cmdbuf, len);
02235 
02236     /* ALERT: check for specific response [ STX ID 'c' 'C' '0' CS ETX ] here? */
02237     if (n = pdv_serial_wait(pdv_p, 200, 7))
02238         pdv_serial_read(pdv_p, cmdbuf, n);
02239 
02240     /* send STX 'c' 'T' '0' 81 ETX (required to "make it so") */
02241     cmdbuf[0] = (char)0x02; /* STX */
02242     cmdbuf[1] = (char)0x01; /* Camera ID 1 */
02243     cmdbuf[2] = 'c';
02244     cmdbuf[3] = 'T';
02245     cmdbuf[4] = '0';
02246     cmdbuf[5] = (char)0x81;
02247     cmdbuf[6] = (char)0x03;
02248     pdv_serial_binary_command(pdv_p, (char *)cmdbuf, 7);
02249 
02250     /* ALERT: check for specific response [ STX ID 'c' 'C' '0' CS ETX ] here? */
02251     if (n = pdv_serial_wait(pdv_p, 200, 7))
02252         pdv_serial_read(pdv_p, cmdbuf, n);
02253 
02254     return 0;
02255 }
02256 
02260 static int
02261 pdv_set_exposure_ptm6710_1020(PdvDev * pdv_p, int value)
02262 {
02263     char    buf[128];
02264 
02265     if ((value < 0) || (value > 9))
02266         return -1;
02267 
02268     sprintf(buf, ":SM%d", value);
02269     pdv_serial_command_flagged(pdv_p, buf, SCFLAG_NORESP);
02270 
02271     return 0;
02272 }
02273 
02277 static int
02278 pdv_set_gain_ptm6710_1020(PdvDev * pdv_p, int value)
02279 {
02280     char    buf[128];
02281 
02282     if ((value < 0) || (value > 0xff))
02283         return -1;
02284 
02285     sprintf(buf, ":GM%02X", value);
02286     pdv_serial_command_flagged(pdv_p, buf, SCFLAG_NORESP);
02287 
02288     return 0;
02289 }
02290 
02295 static int
02296 pdv_set_gain_hc8484(PdvDev * pdv_p, int value)
02297 {
02298     char    buf[128];
02299 
02300     if ((value != 0) && (value != 1))
02301         return -1;
02302     sprintf(buf, "CEG %c", value ? 'H' : 'L');
02303     pdv_serial_command_flagged(pdv_p, buf, SCFLAG_NORESP);
02304 
02305     return 0;
02306 }
02307 
02312 static int
02313 pdv_set_exposure_adimec(PdvDev * pdv_p, int value)
02314 {
02315     char    cmdbuf[32];
02316 
02317     sprintf(cmdbuf, "@IT%d", value);
02318     pdv_serial_command(pdv_p, cmdbuf);
02319     return 0;
02320 }
02321 
02322 static int
02323 pdv_set_gain_adimec(PdvDev * pdv_p, int value)
02324 {
02325     char    cmdbuf[32];
02326 
02327     sprintf(cmdbuf, "@GA%d", value);
02328     pdv_serial_command(pdv_p, cmdbuf);
02329     return 0;
02330 }
02331 
02332 static int
02333 pdv_set_blacklevel_adimec(PdvDev * pdv_p, int value)
02334 {
02335     char    cmdbuf[32];
02336 
02337     sprintf(cmdbuf, "@BL%d;%d", value, value);
02338     pdv_serial_command(pdv_p, cmdbuf);
02339     return 0;
02340 }
02341 
02342 
02347 static int
02348 pdv_set_exposure_specinst(PdvDev * pdv_p, int value)
02349 {
02350     edt_msg(DBG2, "pdv_set_exposure_specinst(%d)\n", value);
02351 
02352     if (pdv_specinst_setparam(pdv_p, 'G', 8, value) != 0)
02353     {
02354         edt_msg(DBG2, "pdv_set_exposure_specinst() apparently FAILED\n");
02355         return -1;
02356     }
02357     return 0;
02358 }
02359 
02364 static int
02365 pdv_set_gain_specinst(PdvDev * pdv_p, int value)
02366 {
02367     edt_msg(DBG2, "pdv_set_gain_specinst(%d)\n", value);
02368 
02369     if (pdv_specinst_setparam(pdv_p, 'G', 11, value) != 0)
02370     {
02371         edt_msg(DBG2, "pdv_set_gain_specinst() apparently FAILED\n");
02372         return -1;
02373     }
02374     return 0;
02375 }
02376 
02382 static int
02383 pdv_set_exposure_su320(PdvDev * pdv_p, int value)
02384 {
02385     char    cmdbuf[32];
02386     char resp[1024];
02387     int n;
02388 
02389     sprintf(cmdbuf, "INT%d", value);
02390     pdv_serial_command(pdv_p, cmdbuf);
02391     pdv_serial_wait(pdv_p, 100, 20);
02392     if ((n = pdv_serial_read(pdv_p, resp, 20)) != 20)
02393         return -1;
02394     return 0;
02395 }
02396 
02397 
02398 static int
02399 pdv_specinst_setparam(PdvDev * pdv_p, char cmd, u_long offset, u_long value)
02400 {
02401     int     ret1, ret2, ret3;
02402     char    resp1[32];
02403     char    resp2[32];
02404     char    buf[32];
02405     u_char  cmdbuf[5];
02406     u_char  offsetbuf[5];
02407     u_char  parambuf[5];
02408     int     si_wait = 200;
02409 
02410     edt_msg(DBG2, "pdv_specinst_setparam(%c %04x %04x)\n", cmd, offset, value);
02411 
02412     dvu_long_to_charbuf(offset, offsetbuf);
02413     dvu_long_to_charbuf(value, parambuf);
02414 
02415     cmdbuf[0] = cmd;
02416 
02417     pdv_serial_binary_command(pdv_p, (char *) cmdbuf, 1);
02418     pdv_serial_wait_next(pdv_p, si_wait, 31);
02419     ret1 = pdv_serial_read(pdv_p, resp1, 31);
02420 
02421     pdv_serial_binary_command(pdv_p, (char *) offsetbuf, 4);
02422     pdv_serial_wait_next(pdv_p, si_wait, 31);
02423     ret2 = pdv_serial_read(pdv_p, buf, 31);
02424 
02425     pdv_serial_binary_command(pdv_p, (char *) parambuf, 4);
02426     pdv_serial_wait_next(pdv_p, si_wait, 31);
02427     ret3 = pdv_serial_read(pdv_p, resp2, 31);
02428 
02429     if ((ret1 != 1) || (ret3 != 1) || (resp1[0] != 'G') || (resp2[0] != 'Y'))
02430     {
02431         edt_msg(DBG1, "invalid or missing serial response from specinst\n");
02432         return -1;
02433     }
02434     return 0;
02435 }
02436 
02450 int
02451 pdv_send_basler_command(PdvDev * pdv_p, int cmd, int rwflag, int len, int data)
02452 {
02453     int       i;
02454     u_char    frame[32];
02455     u_char    rwbit = (rwflag & 0x1) << 7;
02456 
02457     frame[0] = cmd;                           
02458     frame[1] = ((u_char)len & 0xef) | rwbit;
02459     for (i=0; i<len; i++)
02460         frame[i+2] = (data >> (8 * i)) & 0xff;
02461 
02462     return pdv_send_basler_frame(pdv_p, frame, len+2);
02463 }
02464 
02470 int
02471 pdv_set_exposure_basler202k(PdvDev * pdv_p, int value)
02472 {
02473     u_char    rframe[8];
02474 
02475     memset(rframe, 0, 8);
02476     pdv_send_basler_command(pdv_p, 0xa6, 0, 3, value);
02477     pdv_read_basler_frame(pdv_p, rframe, 1);
02478     if (rframe[0] != 0x6) /* ACK */
02479         return -1;
02480     return 0;
02481 }
02482 
02483 int
02484 pdv_set_gain_basler202k(PdvDev * pdv_p, int valuea, int valueb)
02485 {
02486     u_char    rframe[8];
02487 
02488     memset(rframe, 0, 8);
02489     pdv_send_basler_command(pdv_p, 0x80, 0, 2, valuea);
02490     pdv_read_basler_frame(pdv_p, rframe, 1);
02491     if (rframe[0] != 0x6) /* ACK */
02492         return -1;
02493 
02494     memset(rframe, 0, 8);
02495     pdv_send_basler_command(pdv_p, 0x82, 0, 2, valueb);
02496     pdv_read_basler_frame(pdv_p, rframe, 1);
02497     if (rframe[0] != 0x6) /* ACK */
02498         return -1;
02499 
02500     return 0;
02501 }
02502 
02503 int
02504 pdv_set_offset_basler202k(PdvDev * pdv_p, int valuea, int valueb)
02505 {
02506     u_char    rframe[8];
02507 
02508     memset(rframe, 0, 8);
02509     pdv_send_basler_command(pdv_p, 0x81, 0, 2, valuea);
02510     pdv_read_basler_frame(pdv_p, rframe, 1);
02511     if (rframe[0] != 0x6) /* ACK */
02512         return -1;
02513 
02514     memset(rframe, 0, 8);
02515     pdv_send_basler_command(pdv_p, 0x83, 0, 2, valueb);
02516     pdv_read_basler_frame(pdv_p, rframe, 1);
02517     if (rframe[0] != 0x6) /* ACK */
02518         return -1;
02519     return 0;
02520 }
02521 
02538 int
02539 pdv_set_exposure_duncan_ch(PdvDev * pdv_p, int value, int ch)
02540 {
02541     u_char    msg[8];
02542     u_char    rmsg[16];
02543 
02544     msg[0] = 0x04;                              /* LSB size */
02545     msg[1] = 0x00;                              /* MSB size */
02546     msg[2] = 0x14;                              /* command byte */
02547     msg[3] = (u_char)(ch & 0xff);               /* channel*/
02548     msg[4] = (u_char)(value & 0xff);            /* value lsb */
02549     msg[5] = (u_char)((value >> 8) & 0xff);     /* value msb */
02550     pdv_send_duncan_frame(pdv_p, msg, 6);
02551     pdv_read_duncan_frame(pdv_p, rmsg);
02552     return 0;
02553 }
02554 
02571 int
02572 pdv_set_gain_duncan_ch(PdvDev * pdv_p, int value, int ch)
02573 {
02574     u_char    msg[8];
02575     u_char    rmsg[16];
02576 
02577     msg[0] = 0x04;                              /* LSB size */
02578     msg[1] = 0x00;                              /* MSB size */
02579     msg[2] = 0x02;                              /* command byte */
02580     msg[3] = (u_char)(ch & 0xff);               /* channel*/
02581     msg[4] = (u_char)(value & 0xff);            /* value lsb */
02582     msg[5] = (u_char)((value >> 8) & 0xff);     /* value msb */
02583     pdv_send_duncan_frame(pdv_p, msg, 6);
02584     pdv_read_duncan_frame(pdv_p, rmsg);
02585     return 0;
02586 }
02587 
02588 
02593 static void
02594 send_serial_binary_cmd(PdvDev * pdv_p, char *hexstr, int value)
02595 {
02596     int     nb;
02597     u_char  hbuf[2];
02598     char    resp[128];
02599     char    bs[16][3];
02600     int     ret;
02601 
02602     edt_msg(DBG2, "send_serial_binary_cmd(\"%s\", %d)\n", hexstr, value);
02603 
02604     nb = sscanf(hexstr, "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s",
02605         bs[0], bs[1], bs[2], bs[3], bs[4], bs[5], bs[6], bs[7],
02606         bs[8], bs[9], bs[10], bs[11], bs[12], bs[13], bs[14], bs[15]);
02607 
02608     pdv_serial_binary_command(pdv_p, (char *) hbuf, nb);
02609     pdv_serial_wait(pdv_p, 100, 3);
02610 
02611     if (*pdv_p->dd_p->serial_response)
02612         ret = pdv_serial_read(pdv_p, resp, 50);
02613 
02614     {
02615 
02616         edt_msg(DBG2, "serial response <%s> (%d)\n", hex_to_str(resp, ret), ret);
02617     }
02618 }
02619 
02646 int
02647 pdv_auto_set_timeout(PdvDev * pdv_p)
02648 {
02649     Dependent *dd_p = pdv_p->dd_p;
02650     int     user_timeout = dd_p->user_timeout;
02651     int     user_set = dd_p->user_timeout_set;
02652     int     tmult = dd_p->timeout_multiplier;
02653     int     cur_timeout = edt_get_rtimeout(pdv_p);
02654     int     timeout;
02655     int     exposure;
02656     int     pdiv = 1;
02657     int     ret = 0;
02658     int     xfersize;
02659 
02660     /*
02661     * tmult is for cameras with non-standard integration times
02662     */
02663     if (tmult < 1)
02664         tmult = 1;
02665 
02666     /* pixel clock speed less than 5? Hope not! */
02667     if (dd_p->pclock_speed < 5)
02668         dd_p->pclock_speed = 5;
02669     pdiv = dd_p->pclock_speed / 5;
02670 
02671     if (((exposure = dd_p->shutter_speed)) < 500)
02672         exposure = 500; /* conservative enough? hope so */
02673 
02674     xfersize = dd_p->cam_width * dd_p->cam_height * bits2bytes(dd_p->depth);
02675     timeout = (((xfersize * tmult) / 4000) / pdiv) + exposure;
02676 
02677     edt_msg(DBG2, "pdv_auto_set_timeout(): current %d new %d exposure %d pclock %d pdiv %d mult %d user %d\n",
02678         cur_timeout, timeout, exposure, dd_p->pclock_speed, pdiv,
02679         tmult, user_timeout);
02680 
02681     /*
02682     * sticking an 0.5 sec min in here because sometimes small cameras are
02683     * problematic
02684     */
02685     if (timeout < 500)
02686         timeout = 500;
02687 
02688     if (user_set)
02689     {
02690         edt_msg(DBG2, "  user set to %d - overriding auto\n", user_timeout);
02691 
02692         if (timeout > user_timeout && user_timeout != 0)
02693         {
02694             edt_msg(DBG2, "  Warning: exposure %d msecs user specified timeout %d msecs\n", dd_p->shutter_speed, user_timeout);
02695             edt_msg(DBG2, "  not automatically increased since user specified\n");
02696         }
02697     }
02698     else
02699     {
02700         int     targ;
02701 
02702         edt_msg(DBG2, "  setting picture timeout from %d to %d\n", cur_timeout, timeout);
02703         targ = timeout;
02704         ret = edt_set_rtimeout(pdv_p, targ);
02705     }
02706     return ret;
02707 }
02708 
02728 int
02729 pdv_set_gain(PdvDev * pdv_p, int value)
02730 {
02731     int     ret;
02732     Dependent *dd_p = pdv_p->dd_p;
02733 
02734     edt_msg(DBG2, "pdv_set_gain(%d)\n", value);
02735 
02736     dd_p->gain = value;
02737     ret = edt_set_dependent(pdv_p, dd_p);
02738 
02739     if ((strlen(dd_p->serial_gain) > 0) && (dd_p->serial_format == SERIAL_BINARY))
02740         send_serial_binary_cmd(pdv_p, dd_p->serial_gain, value);
02741 
02742     else if (dd_p->serial_format == SERIAL_ASCII)
02743     {
02744         char cmdstr[64] = {'\0'};
02745         int n = check_valid_formatstr(dd_p->serial_gain); 
02746 
02747         if (n == 0) /* no % formatting, use old method */
02748             sprintf(cmdstr, "%s %d", dd_p->serial_gain, value);
02749         else if ((n > 0) && (n < 5))
02750             sprintf(cmdstr, dd_p->serial_gain, value, value, value, value);
02751 
02752         if (cmdstr)
02753         {
02754             ret = pdv_serial_command_flagged(pdv_p, cmdstr, SCFLAG_NORESP);
02755 
02756             pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, 64);
02757             if (*pdv_p->dd_p->serial_response)
02758                 pdv_serial_read(pdv_p, cmdstr, 63);
02759         }
02760     }
02761 
02762     else if ((strncasecmp(dd_p->camera_class, "Hamamatsu", 9) == 0)
02763         && ((strncasecmp(dd_p->camera_model, "C8484", 5) == 0)
02764         || (strncasecmp(dd_p->camera_model, "8484", 4) == 0)))
02765     {
02766         ret = pdv_set_gain_hc8484(pdv_p, value);
02767     }
02768 
02769     else if ((dd_p->camera_shutter_timing == SPECINST_SERIAL)
02770         || (dd_p->camera_shutter_speed == SPECINST_SERIAL))
02771     {
02772         ret = pdv_set_gain_specinst(pdv_p, value);
02773     }
02774     else if (dd_p->camera_shutter_timing == TOSHIBA_SERIAL)
02775     {
02776         ret = pdv_set_gain_toshiba(pdv_p, value);
02777     }
02778     else if (dd_p->camera_shutter_timing == COHU_SERIAL)
02779     {
02780         ret = pdv_set_gain_cohu(pdv_p, value);
02781     }
02782     else if (dd_p->set_gain == SMD_SERIAL)      /* smd binary serial method */
02783     {
02784         ret = pdv_set_gain_smd(pdv_p, value);
02785     }
02786     else if ((strncasecmp(dd_p->camera_class, "Adimec", 6) == 0))
02787     {
02788         ret = pdv_set_gain_adimec(pdv_p, value);
02789     }
02790 
02791     else if ((strncasecmp(dd_p->camera_class, "PULNiX", 6) == 0)
02792         && ((strncasecmp(dd_p->camera_model, "TM-6710", 7) == 0)
02793         || (strncasecmp(dd_p->camera_model, "TM-1020", 7) == 0)))
02794     {
02795         ret = pdv_set_gain_ptm6710_1020(pdv_p, value);
02796     }
02797 
02798     else if ((dd_p->set_gain == AIA_MC4)        /* mode cntl 4 method */
02799         && (dd_p->xilinx_rev >= 1 && dd_p->xilinx_rev <= 32))
02800     {
02801         u_int   util2 = edt_reg_read(pdv_p, PDV_UTIL2);
02802         u_int   mcl = edt_reg_read(pdv_p, PDV_MODE_CNTL);
02803 
02804         edt_reg_write(pdv_p, PDV_UTIL2, util2 & ~PDV_MC4);
02805         edt_reg_write(pdv_p, PDV_MODE_CNTL, dd_p->gain);
02806         edt_reg_write(pdv_p, PDV_UTIL2, util2 | PDV_MC4);
02807         edt_reg_write(pdv_p, PDV_MODE_CNTL, mcl);
02808     }
02809 
02810     edt_msg(DBG2, "pdv_set_gain returning %d\n", ret);
02811     return (ret);
02812 }
02813 
02817 static int
02818 pdv_set_gain_smd(PdvDev * pdv_p, int value)
02819 {
02820     char    buf[128];
02821     char    smd_config;
02822     int     smd_reg1;
02823     int     ret = 0;
02824 
02825     if (Smd_type == NOT_SET)
02826     {
02827         Smd_type = smd_read_reg(pdv_p, SMD_READ_CAMTYPE);
02828         if ((Smd_type & 0xfff) == 0xfff)        /* sometimes there's garbage
02829                                                 * at first; if so try again */
02830                                                 Smd_type = smd_read_reg(pdv_p, SMD_READ_CAMTYPE);
02831     }
02832 
02833     switch (Smd_type)
02834     {
02835     case SMD_TYPE_4M4:
02836         buf[0] = (char) SMD_4M4_READ_R1;
02837         pdv_serial_binary_command(pdv_p, buf, 1);
02838         pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout,
02839             pdv_p->dd_p->serial_respcnt);
02840         if (pdv_serial_read(pdv_p, buf, 63) == 1)
02841         {
02842             smd_config = buf[0];
02843 
02844             buf[0] = (char) SMD_4M4_WRITE_R1;
02845             pdv_serial_binary_command(pdv_p, buf, 1);
02846 
02847             if (value == 0)
02848                 smd_config &= ~SMD_4M4_R1_GAIN;
02849             else
02850                 smd_config |= SMD_4M4_R1_GAIN;
02851             buf[0] = smd_config;
02852             pdv_serial_binary_command(pdv_p, buf, 1);
02853             /* SMD doesn't resp but do a dummy wait to make sure its done */
02854             pdv_serial_wait(pdv_p, 100, 64);
02855         }
02856         else
02857             ret = -1;
02858         break;
02859 
02860     case SMD_TYPE_1M30P:
02861         buf[0] = (u_char) SMD_1M30P_REG_W_LS_GAIN;
02862         buf[1] = value & 0xff;
02863         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
02864 
02865         buf[0] = (u_char) SMD_1M30P_REG_W_MS_GAIN;
02866         buf[1] = (value & 0xff00) >> 8;
02867         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
02868 
02869         /* SMD doesn't respond but do a dmy wait to make sure its done */
02870         pdv_serial_wait(pdv_p, 100, 64);
02871         break;
02872 
02873     case SMD_TYPE_1M15P:
02874     case SMD_TYPE_6M3P:
02875         if ((smd_reg1 = smd_read_reg(pdv_p, SMD_1M15P_READ_R1)) == -1)
02876         {
02877             edt_msg(PDVWARN, "libpdv: no response from SMD R1 reg read\n");
02878             return -1;
02879         }
02880 
02881         buf[0] = (u_char) SMD_1M15P_WRITE_R1; /* same for 6M3P */
02882 
02883         /*
02884         * valid values for this camera are 0 or 1
02885         */
02886         if (value == 0)
02887             buf[1] = smd_reg1 &~ SMD_1M15P_R1_GAIN;
02888         else if (value == 1)
02889             buf[1] = smd_reg1 | SMD_1M15P_R1_GAIN;
02890         else return -1;
02891 
02892         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
02893         pdv_p->dd_p->gain = value;
02894 
02895         /* SMD doesn't respond but do a dmy wait to make sure its done */
02896         pdv_serial_wait(pdv_p, 100, 64);
02897         break;
02898     }
02899 
02900     return ret;
02901 }
02902 
02911 int
02912 pdv_set_gain_ch(PdvDev * pdv_p, int value, int chan)
02913 {
02914     int     ret = -1;
02915 
02916     /* ALERT -- no methods implemented since ddcam went away... */
02917     edt_msg(DBG2, "pdv_set_gain_ch(%d, [%c]) ret %d\n",
02918         value, (chan == 1) ? 'A' : (chan == 2) ? 'B' : '?', ret);
02919     return (ret);
02920 }
02921 
02939 int
02940 pdv_set_blacklevel(PdvDev * pdv_p, int value)
02941 {
02942     Dependent *dd_p = pdv_p->dd_p;
02943     int     ret;
02944 
02945     edt_msg(DBG2, "pdv_set_blacklevel(%d)\n", value);
02946 
02947     dd_p->level = value;
02948     ret = edt_set_dependent(pdv_p, dd_p);
02949 
02950     if (dd_p->set_offset == SMD_SERIAL) /* smd binary serial method */
02951         ret = pdv_set_blacklevel_smd(pdv_p, value);
02952 
02953     else if (dd_p->camera_shutter_timing == COHU_SERIAL)
02954     {
02955         ret = pdv_set_blacklevel_cohu(pdv_p, value);
02956     }
02957 
02958     else if ((strncasecmp(dd_p->camera_class, "Adimec", 6) == 0))
02959     {
02960         ret = pdv_set_blacklevel_adimec(pdv_p, value);
02961     }
02962 
02963     else if ((strlen(dd_p->serial_offset) > 0) && (dd_p->serial_format == SERIAL_BINARY))
02964     {
02965         send_serial_binary_cmd(pdv_p, dd_p->serial_offset, value);
02966     }
02967 
02968     else if (dd_p->serial_format == SERIAL_ASCII)
02969     {
02970         char cmdstr[64] = {'\0'};
02971         int n = check_valid_formatstr(dd_p->serial_offset); 
02972 
02973         if (n == 0) /* no % formatting, use old method */
02974             sprintf(cmdstr, "%s %d", dd_p->serial_offset, value);
02975         else if ((n > 0) && (n < 5))
02976             sprintf(cmdstr, dd_p->serial_offset, value, value, value, value);
02977 
02978         if (cmdstr[0])
02979         {
02980             ret = pdv_serial_command_flagged(pdv_p, cmdstr, SCFLAG_NORESP);
02981 
02982             pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, 64);
02983             if (*pdv_p->dd_p->serial_response)
02984                 pdv_serial_read(pdv_p, cmdstr, 63);
02985         }
02986     }
02987 
02988     edt_msg(DBG2, "pdv_set_blacklevel() %d\n", ret);
02989     return (ret);
02990 }
02991 
02992 static int
02993 pdv_set_blacklevel_smd(PdvDev * pdv_p, int value)
02994 {
02995     char    buf[128];
02996     int     ret = 0;
02997     int     tmpval = value & 0xfff;
02998     int     smd_reg2, smd_reg3;
02999 
03000     if (Smd_type == NOT_SET)
03001     {
03002         Smd_type = smd_read_reg(pdv_p, SMD_READ_CAMTYPE);
03003         if ((Smd_type & 0xfff) == 0xfff)        /* sometimes there's garbage
03004                                                 * at first; if so try again */
03005                                                 Smd_type = smd_read_reg(pdv_p, SMD_READ_CAMTYPE);
03006     }
03007 
03008     switch (Smd_type)
03009     {
03010     case SMD_TYPE_4M4:
03011     case SMD_TYPE_BT25:
03012         break;
03013 
03014     case SMD_TYPE_1M30P:
03015         buf[0] = (u_char) SMD_1M30P_REG_W_LS_OFFSET;
03016         buf[1] = value & 0xff;
03017         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
03018 
03019         buf[0] = (u_char) SMD_1M30P_REG_W_MS_OFFSET;
03020         buf[1] = (value & 0xff00) >> 8;
03021         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
03022 
03023         /* SMD doesn't respond but do a dmy wait to make sure its done */
03024         pdv_serial_wait(pdv_p, 100, 64);
03025         break;
03026 
03027     case SMD_TYPE_1M15P:
03028         if ((smd_reg3 = smd_read_reg(pdv_p, SMD_1M15P_READ_R3)) == -1)
03029         {
03030             edt_msg(PDVWARN, "libpdv: no response from Dalstar R3 reg read\n");
03031             ret = -1;
03032         }
03033 
03034         smd_reg2 =  tmpval >> 4;
03035         smd_reg3 = (smd_reg3 & ~0x0f) | (tmpval & 0x0f);
03036 
03037         /* write R3 */
03038         buf[0] = (u_char) SMD_1M15P_WRITE_R3;
03039         buf[1] = (u_char) smd_reg3;
03040         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
03041 
03042         /* must write R2 last */
03043         buf[0] = (u_char) SMD_1M15P_WRITE_R2;
03044         buf[1] = (u_char) smd_reg2;
03045         pdv_serial_binary_command(pdv_p, (char *) buf, 2);
03046 
03047         /* SMD doesn't respond but do a dmy wait to make sure its done */
03048         pdv_serial_wait(pdv_p, 100, 64);
03049         break;
03050 
03051     default:
03052         ret = -1;
03053     }
03054 
03055     return ret;
03056 }
03057 
03066 int
03067 pdv_set_aperture(PdvDev * pdv_p, int value)
03068 {
03069     edt_msg(PDVWARN, "pdv_set_aperture is OBSOLETE\n");
03070     return (-1);
03071 }
03072 
03114 int
03115 pdv_set_binning(PdvDev * pdv_p, int xval, int yval)
03116 {
03117     int     ret = -1;
03118     int     newvskip, newhskip, newwidth, newheight;
03119     Dependent *dd_p = pdv_p->dd_p;
03120 
03121     if (((xval != 1) && (xval % 2)) || ((yval != 1) && (yval % 2)))
03122     {
03123         edt_msg(PDVWARN, "pdv_set_binning(%d, %d) -- invalid value\n", xval, yval);
03124         return -1;
03125     }
03126 
03127     edt_msg(DBG2, "pdv_set_binning(%d, %d)\n", xval, yval);
03128 
03129     if (strcmp(dd_p->serial_binning, "BIN") == 0)       /* DVC */
03130     {
03131         ret = pdv_set_binning_dvc(pdv_p, xval, yval);
03132     }
03133     else if (strcmp(dd_p->serial_binning, "B=") == 0)   /* ATMEL */
03134     {
03135         ret = pdv_set_binning_generic(pdv_p, xval - 1);
03136     }
03137     else if (*dd_p->serial_binning)     /* Generic */
03138     {
03139         /* wing it */
03140         ret = pdv_set_binning_generic(pdv_p, xval);
03141     }
03142     else
03143         return -1;
03144 
03145     if (ret)
03146         return ret;
03147 
03148     if (dd_p->binx < 1)
03149         dd_p->binx = 1;
03150     if (dd_p->biny < 1)
03151         dd_p->biny = 1;
03152 
03153     newwidth = (((pdv_get_width(pdv_p) * dd_p->binx) / xval) / 4) * 4;
03154     newheight = (((pdv_get_height(pdv_p) * dd_p->biny) / yval)) ;
03155 
03156     if (dd_p->roi_enabled)
03157     {
03158         newhskip = (dd_p->hskip * dd_p->binx) / xval;
03159         newvskip = (dd_p->vskip * dd_p->biny) / yval;
03160         ret = pdv_set_roi(pdv_p, newhskip, newwidth, newvskip, newheight);
03161     }
03162 
03163     if (!ret)
03164     {
03165         dd_p->binx = xval;
03166         dd_p->biny = yval;
03167     }
03168 
03169     return (ret);
03170 }
03171 
03177 static int
03178 pdv_set_binning_generic(PdvDev * pdv_p, int value)
03179 {
03180     char    cmdstr[64];
03181     Dependent *dd_p = pdv_p->dd_p;
03182 
03183     if (dd_p->serial_binning[strlen(dd_p->serial_binning) - 1] == '=')  /* atmel */
03184         sprintf(cmdstr, "%s%d", dd_p->serial_binning, value);
03185     else
03186         sprintf(cmdstr, "%s %d", dd_p->serial_binning, value);
03187     pdv_serial_command_flagged(pdv_p, cmdstr, SCFLAG_NORESP);
03188 
03189     return (0);
03190 }
03191 
03192 
03205 int
03206 pdv_get_exposure(PdvDev * pdv_p)
03207 {
03208     edt_msg(DBG2, "pdv_get_exposure() %d\n", pdv_p->dd_p->shutter_speed);
03209 
03210     return (pdv_p->dd_p->shutter_speed);
03211 }
03212 
03213 void
03214 pdv_set_defaults(PdvDev * pdv_p)
03215 {
03216     Dependent *dd_p = pdv_p->dd_p;
03217 
03218     if (dd_p->default_shutter_speed != NOT_SET)
03219         pdv_set_exposure(pdv_p, dd_p->default_shutter_speed);
03220     if (dd_p->default_gain != NOT_SET)
03221         pdv_set_gain(pdv_p, dd_p->default_gain);
03222     if (dd_p->default_offset != NOT_SET)
03223         pdv_set_blacklevel(pdv_p, dd_p->default_offset);
03224 }
03225 
03237 int
03238 pdv_read_response(PdvDev * pdv_p, char *buf)
03239 {
03240     int     len;
03241 
03242     /*
03243     * serial_timeout comes from the config file, or default of 1 sec
03244     */
03245     len = pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, 2048);
03246     if (len)
03247         pdv_serial_read(pdv_p, buf, len);
03248     return len;
03249 }
03250 
03251 
03265 int
03266 pdv_get_gain(PdvDev * pdv_p)
03267 {
03268     edt_msg(DBG2, "pdv_get_gain() %d\n", pdv_p->dd_p->gain);
03269 
03270     return (pdv_p->dd_p->gain);
03271 }
03272 
03273 
03283 int
03284 pdv_get_blacklevel(PdvDev * pdv_p)
03285 {
03286     edt_msg(DBG2, "pdv_get_blacklevel() %d\n", pdv_p->dd_p->level);
03287 
03288     return (pdv_p->dd_p->level);
03289 }
03290 
03299 int
03300 pdv_get_aperture(PdvDev * pdv_p)
03301 {
03302     edt_msg(PDVWARN, "pdv_get_aperture is OBSOLETE\n");
03303     return (-1);
03304 }
03305 
03316 void
03317 pdv_invert(PdvDev * pdv_p, int val)
03318 {
03319     u_int   data_path;
03320     int     ret;
03321 
03322     edt_msg(DBG2, "pdv_invert()\n");
03323 
03324     if (pdv_p->devid == PDVFOI_ID)
03325     {
03326         char    buf[64];
03327 
03328         pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, pdv_p->dd_p->serial_respcnt);
03329         if (*pdv_p->dd_p->serial_response)
03330             ret = pdv_serial_read(pdv_p, buf, 63);
03331     }
03332 
03333     /* data_path = edt_reg_read(pdv_p, PDV_DATA_PATH); */
03334     data_path = pdv_p->dd_p->datapath_reg;
03335 
03336     edt_msg(DBG2, "pdv_invert(%d)\n", val);
03337 
03338     if (val)
03339         data_path |= PDV_INVERT;
03340     else
03341         data_path &= ~PDV_INVERT;
03342 
03343     edt_reg_write(pdv_p, PDV_DATA_PATH, data_path);
03344     pdv_p->dd_p->datapath_reg = data_path;
03345 }
03346 
03352 u_short
03353 pdv_get_interlaced(PdvDev * pdv_p)
03354 
03355 {
03356     edt_msg(DBG2, "pdv_get_interlaced() %u\n", pdv_p->dd_p->interlace);
03357 
03358     return (pdv_p->dd_p->interlace);
03359 }
03360 
03383 int
03384 pdv_force_single(PdvDev * pdv_p)
03385 {
03386     return pdv_p->dd_p->force_single;
03387 }
03388 
03396 int
03397 pdv_variable_size(PdvDev * pdv_p)
03398 {
03399     return pdv_p->dd_p->variable_size;
03400 }
03401 
03402 
03403 
03423 int
03424 pdv_serial_read_nullterm(PdvDev * pdv_p, char *buf, int size, int nullterm)
03425 {
03426 #define PKT_OVERHEAD 2
03427 #define PKT_SIZE_MAX 15
03428 
03429     int     bytesReturned;
03430     Dependent *dd_p;
03431 
03432     if (pdv_p == NULL || pdv_p->dd_p == NULL)
03433         return 0;
03434 
03435     dd_p = pdv_p->dd_p;
03436 
03437     if (buf == NULL || pdv_p == NULL || size == 0)
03438         return (-1);
03439 
03440     if (pdv_p->devid == PDVFOI_ID)
03441     {
03442         char    tmpbuf[256];
03443 
03444         bytesReturned = edt_get_msg(pdv_p, tmpbuf, 256);
03445         if (bytesReturned <= PKT_OVERHEAD)
03446             return (0);
03447         if (Pdv_debug)
03448         {
03449             int     i, num = bytesReturned;
03450 
03451             if (num > 16)       /* limit number of bytes printed to 16 */
03452                 num = 16;
03453             edt_msg(DBG2, "pdv_serial_read(<");
03454             for (i = 0; i < num; i++)
03455             {
03456                 edt_msg(DBG2, "%02x", (u_char) tmpbuf[i]);
03457                 if (i + 1 < num)
03458                     edt_msg(DBG2, ", ");
03459                 else
03460                     break;
03461             }
03462             edt_msg(DBG2, ">, %d-%d\n", bytesReturned, size);
03463         }
03464         if (bytesReturned > size)
03465         {
03466             memcpy(buf, &tmpbuf[PKT_OVERHEAD], size);
03467             edt_msg(DBG2, "pdv_serial_read(%d) %d\n", size, bytesReturned);
03468             return (size);
03469         }
03470         else
03471         {
03472             bytesReturned -= PKT_OVERHEAD;
03473             memcpy(buf, &tmpbuf[PKT_OVERHEAD], bytesReturned);
03474             if (nullterm)
03475                 buf[bytesReturned] = 0;
03476             edt_msg(DBG2, "pdv_serial_read(%d) %d\n", size, bytesReturned);
03477             return (bytesReturned);
03478         }
03479     }
03480 
03481 #if 0
03482     if (!pdv_get_width(pdv_p))
03483     {
03484         edt_msg(DBG2, "warning - serial_read called with uninitialized camera\n");
03485         return (0);
03486     }
03487 #endif
03488 
03489     bytesReturned = edt_get_msg(pdv_p, buf, size);
03490     assert(bytesReturned <= size);
03491 
03492     if (nullterm)
03493         buf[bytesReturned] = 0;
03494 
03495     if (Pdv_debug)
03496     {
03497         int     i, num = bytesReturned;
03498 
03499         if (num > 16)           /* limit number of bytes printed to 16 */
03500             num = 16;
03501         edt_msg(DBG2, "pdv_serial_read(<");
03502         for (i = 0; i < num; i++)
03503         {
03504             edt_msg(DBG2, "%02x", (u_char) buf[i]);
03505             if (i + 1 < num)
03506                 edt_msg(DBG2, ", ");
03507             else
03508                 break;
03509         }
03510         edt_msg(DBG2, ">, %d)\n", size);
03511     }
03512     return bytesReturned;
03513 }
03514 
03546 int
03547 pdv_serial_read(PdvDev * pdv_p, char *buf, int count)
03548 {
03549 
03550     return pdv_serial_read_nullterm(pdv_p,buf,count,TRUE);
03551 }
03552 
03559 int
03560 pdv_send_msg(PdvDev *ed, int chan, const char *buf, int size)
03561 {
03562     int i, ret = 0;
03563     int pause = ed->dd_p->pause_for_serial;
03564     char bbuf[32];
03565 
03566     /* sleep between bytes if indicated */
03567     if (pause)
03568     {
03569         for (i=0; i<size; i++)
03570         {
03571             bbuf[0] = buf[i];
03572             edt_msleep(ed->dd_p->pause_for_serial);
03573             if ((ret = edt_send_msg(ed, chan, bbuf, 1)) != 0)
03574                 return ret;
03575         }
03576         return ret;
03577     }
03578     else return edt_send_msg(ed, chan, buf, size);
03579 }
03580 
03596 int
03597 pdv_serial_write_single_block(PdvDev * pdv_p, const char *buf, int size)
03598 {
03599     int     ret;
03600     Dependent *dd_p;
03601 
03602     if (size == 0)
03603         return (-1);
03604 
03605     if (Pdv_debug)
03606     {
03607         int     i, num = size;
03608 
03609         if (num > 16)           /* limit number of bytes printed to 16 */
03610             num = 16;
03611         edt_msg(DBG2, "pdv_serial_write_single_block(<");
03612         for (i = 0; i < num; i++)
03613         {
03614             edt_msg(DBG2, "%02x", (u_char) buf[i]);
03615             if (i + 1 < num)
03616                 edt_msg(DBG2, ", ");
03617             else
03618                 break;
03619         }
03620         edt_msg(DBG2, ">, %d)\n", size);
03621     }
03622 
03623     if (buf == NULL || pdv_p == NULL || pdv_p->dd_p == NULL)
03624         return (-1);
03625     dd_p = pdv_p->dd_p;
03626 
03627     ret = pdv_send_msg(pdv_p, pdv_p->channel_no, buf, size);
03628     return (ret);
03629 }
03630 
03639 int
03640 pdv_serial_write_available(PdvDev *pdv_p)
03641 
03642 {
03643 
03644     int avail;
03645 
03646     edt_ioctl(pdv_p, EDTG_SERIAL_WRITE_AVAIL, &avail);
03647 
03648     return avail;
03649 
03650 }
03651 
03652 static int pdv_serial_block_size = 512;
03653 
03659 void pdv_set_serial_block_size(int newsize)
03660 {
03661     pdv_serial_block_size = newsize;
03662 }
03663 
03670 int
03671 pdv_get_serial_block_size()
03672 {
03673     return pdv_serial_block_size;
03674 }
03675 
03679 int
03680 pdv_serial_read_enable(PdvDev *pdv_p)
03681 
03682 {
03683 
03684     edt_reg_or(pdv_p, PDV_SERIAL_DATA_CNTL,
03685         PDV_EN_TX | PDV_EN_RX |
03686         PDV_EN_RX_INT | PDV_EN_DEV_INT);
03687 
03688     edt_set_remote_intr(pdv_p, TRUE);
03689 
03690     return 0;
03691 }
03692 
03709 int
03710 pdv_serial_write(PdvDev *pdv_p, const char *buf, int size)
03711 
03712 {
03713     int avail;
03714     int left = size;
03715     int ret = 0;
03716     int offset = 0;
03717     int speed = pdv_get_baud(pdv_p);
03718     int sleepval;
03719     int chunk = pdv_serial_block_size;
03720 
03721     if (speed != 0)
03722         sleepval = speed/10;
03723     else
03724         sleepval = 10;
03725 
03726     sleepval = (chunk * 1000) / sleepval; /* time to send chunk chars */
03727 
03728     avail = pdv_serial_write_available(pdv_p);
03729     if (avail > size)
03730     {
03731         return pdv_serial_write_single_block(pdv_p, buf, size);
03732     }
03733     else
03734     {
03735         left -= avail;
03736         offset += avail;
03737 
03738 #ifdef DBG_SERIAL
03739         printf("Writing %d chars\n", avail);
03740 #endif
03741 
03742         ret = pdv_serial_write_single_block(pdv_p, buf, avail);
03743 
03744         if (ret != 0)
03745             return ret;
03746         while (left > 0)
03747         {
03748             edt_msleep(sleepval);
03749             avail = pdv_serial_write_available(pdv_p);
03750             if (avail > 0)
03751             {
03752                 if ( avail > left)
03753                 {
03754                     avail = left;
03755                     left = 0;
03756                 }
03757                 else
03758                 {
03759                     left -= avail;
03760                 }
03761 
03762 #ifdef DBG_SERIAL
03763                 printf("Writing %d chars\n", avail);
03764 #endif
03765                 ret = pdv_serial_write_single_block(pdv_p, buf+offset, avail);
03766                 if (ret != 0)
03767                     return ret;
03768                 offset += avail;
03769 
03770             }
03771         }
03772     }
03773     return 0;
03774 }
03775 
03792 int
03793 pdv_serial_read_blocking(PdvDev *pdv_p, char *buf, int size)
03794 
03795 {
03796     int left = size;
03797     int ret = 0;
03798     int offset = 0;
03799 
03800 
03801     int avail = 1024;
03802     int speed = pdv_get_baud(pdv_p);
03803     int sleepval;
03804     int chunk = pdv_serial_block_size;
03805 
03806     if (speed != 0)
03807         sleepval = speed/10;
03808     else
03809         sleepval = 10;
03810 
03811     sleepval = (chunk * 1000) / sleepval; /* time to send chunk chars */
03812 
03813     if (avail > size)
03814     {
03815         sleepval = (size * 1000) / sleepval;
03816 
03817         pdv_serial_wait(pdv_p, sleepval, size);
03818 
03819         return pdv_serial_read(pdv_p, buf, size);
03820     }
03821     else
03822     {
03823 
03824         while (left > 0)
03825         {
03826             avail = pdv_serial_wait(pdv_p, sleepval, chunk);
03827             if (avail)
03828             {
03829                 if ( avail > left)
03830                 {
03831                     avail = left;
03832                     left = 0;
03833                 }
03834                 else
03835                 {
03836                     left -= avail;
03837                 }
03838 
03839 #ifdef DBG_SERIAL
03840                 printf("Reading %d chars total = %d\n", avail, offset + avail);
03841 #endif
03842                 ret = pdv_serial_read(pdv_p, buf+offset, avail);
03843                 offset += avail;
03844 
03845             }
03846 
03847 
03848         }
03849 
03850     }
03851 
03852     return 0;
03853 
03854 }
03855 
03856 
03900 int
03901 pdv_serial_command(PdvDev * pdv_p, const char *cmd)
03902 {
03903     /* older comment:
03904     * Sends a serial AIA command convenience wrapper for pdv_serial_write()
03905     * -- takes the command string and adds the '\r' and deals with the
03906     * string length issue... Prepends a 'c if FOI. Because of the FOI
03907     * issue, applications should ALWAYS use this or
03908     * pdv_serial_binary_command instead of calling pdv_serial_write
03909     * directly.
03910     * 
03911     * UNLESS -- serial_format is SERIAL_PULNIX_1010, in which case it prepends an
03912     * STX (0x2) and appends an ETX (0x3)
03913     */
03914     return pdv_serial_command_flagged(pdv_p, cmd, 0);
03915 }
03916 
03933 int
03934 pdv_serial_command_flagged(PdvDev * pdv_p, const char *cmd, u_int flag)
03935 {
03936     char    *buf;
03937     int     ret;
03938     int     i;
03939     size_t     len=0;
03940     int     bufsize=8; /* arbitrary but should handle whatever extra is tacked on below */
03941     const char    *p = cmd;
03942 
03943     if (pdv_p == NULL || pdv_p->dd_p == NULL)
03944         return -1;
03945 
03946     /* find the size (new, was fixed @ 256, now dynamic) */
03947     while (*p++)
03948         ++bufsize;
03949     buf = (char *)malloc(bufsize+16);
03950     /* 16 is arbitrary, to allow for serial_prefix/serial_term */
03951 
03952     /* prepend "c" for FOI */
03953     if (pdv_p->devid == PDVFOI_ID)
03954     {
03955         buf[len++] = 'c';
03956 
03957         /* 't' says don't wait for response */
03958         if (flag & SCFLAG_NORESP)
03959             buf[len++] = 't';
03960         buf[len++] = ' ';
03961     }
03962 
03963     /* new:  serial_prefix -- prepend if nonzero */
03964     if (*pdv_p->dd_p->serial_prefix)
03965     {
03966         strcpy(&(buf[len]), pdv_p->dd_p->serial_prefix);
03967         len += strlen(pdv_p->dd_p->serial_prefix);
03968     }
03969 
03970     /* strip off  CR or LF, then add prepend/append STX/ETX */
03971     if (pdv_p->dd_p->serial_format == SERIAL_PULNIX_1010)
03972     {
03973         buf[len++] = 0x02;      /* prepend STX */
03974         for (i = 0; i < bufsize; i++)
03975             if (cmd[i] == '\r' || cmd[i] == '\n' || cmd[i] == 0)
03976                 break;
03977             else
03978                 buf[len++] = cmd[i];
03979         buf[len++] = 0x03;      /* append ETX */
03980     }
03981     else
03982     {
03983         /* strip off  CR or LF, then add serial_term */
03984 
03985         for (i = 0; i < bufsize; i++)
03986         {
03987             if (cmd[i] == '\r' || cmd[i] == '\n' || cmd[i] == 0)
03988                 break;
03989             else
03990                 buf[len++] = cmd[i];
03991         }
03992         /* ALERT! need to change for FOI if \\n! */
03993         sprintf(&(buf[len]), "%s", pdv_serial_term(pdv_p));
03994         len += strlen(pdv_serial_term(pdv_p));
03995     }
03996 
03997     if (Pdv_debug)
03998         debug_print_serial_command(buf);
03999     ret = pdv_serial_write(pdv_p, buf, len);
04000 
04001     free(buf);
04002     return (ret);
04003 }
04004 
04013 char   *
04014 pdv_serial_term(PdvDev * pdv_p)
04015 {
04016     return pdv_p->dd_p->serial_term;
04017 }
04018 
04027 char   *
04028 pdv_serial_prefix(PdvDev * pdv_p)
04029 {
04030     return pdv_p->dd_p->serial_prefix;
04031 }
04032 
04047 void
04048 pdv_set_serial_delimiters(PdvDev *pdv_p, char *prefix, char *term)
04049 
04050 {
04051     if (prefix)
04052         strncpy(pdv_p->dd_p->serial_prefix,prefix, sizeof(pdv_p->dd_p->serial_prefix)-1);
04053     else
04054         pdv_p->dd_p->serial_prefix[0] = 0;
04055 
04056     if (term)
04057         strncpy(pdv_p->dd_p->serial_term,term, sizeof(pdv_p->dd_p->serial_term)-1);
04058     else
04059         pdv_p->dd_p->serial_term[0] = 0;
04060 
04061     edt_set_dependent(pdv_p,pdv_p->dd_p);
04062 }
04063 
04064 
04065 /* debug print ASCII serial command string, from pdv_serial_command */
04066 static void
04067 debug_print_serial_command(char *cmd)
04068 {
04069     char    tmpbuf[256];
04070     char   *p = cmd;
04071     char   *pp = tmpbuf;
04072     int    len=0;
04073 
04074     while (*p != '\0')
04075     {
04076         if (*p == '\r')
04077         {
04078             sprintf(pp, "\\r");
04079             pp += 2;
04080             len += 2;
04081             ++p;
04082         }
04083         else if (*p == '\n')
04084         {
04085             sprintf(pp, "\\n");
04086             pp += 2;
04087             len += 2;
04088             ++p;
04089         }
04090         else if (!isprint(*p))
04091         {
04092             sprintf(pp, "<%02x>", (*p) & 0xff);
04093             pp += 4;
04094             len += 4;
04095             ++p;
04096         }
04097         else
04098         {
04099             *(pp++) = *(p++);
04100             ++len ;
04101         }
04102         if (len > 250) /* arbitrary max, just bail out so we don't crash */
04103             break;
04104     }
04105     *pp = '\0';
04106     edt_msg(DBG2, "pdv_serial_command(\"%s\")\n", tmpbuf);
04107 }
04108 
04139 int
04140 pdv_serial_binary_command(PdvDev * pdv_p, const char *cmd, int len)
04141 {
04142     return pdv_serial_binary_command_flagged(pdv_p, cmd, len, 0);
04143 }
04144 
04145 
04152 int
04153 pdv_send_basler_frame(PdvDev * pdv_p, u_char *cmd, int len)
04154 {
04155     int i;
04156     u_char frame[128];
04157     u_char *p = frame;
04158     u_char bcc = 0;
04159 
04160     *p++ = 0x02;
04161     for (i=0; i<len; i++)
04162     {
04163         bcc ^= cmd[i];
04164         *p++ = cmd[i];
04165     }
04166     *p++ = bcc;
04167     *p++ = 0x03;
04168 
04169     return pdv_serial_binary_command_flagged(pdv_p, (char *)frame, len+3, 0);
04170 }
04171 
04178 int
04179 pdv_read_basler_frame(PdvDev * pdv_p, u_char *frame, int len)
04180 {
04181     int n, nn;
04182     char tmpbuf[128];
04183     char *p;
04184 
04185     n = pdv_serial_wait(pdv_p, 500, len);
04186     if (n < 1)
04187         return 0;
04188 
04189     nn = pdv_serial_read(pdv_p, tmpbuf, n);
04190 
04191     if (tmpbuf[0] == 0x06) /* ACK */
04192     {
04193         frame[0] = 0x06;
04194         return 1;
04195     }
04196 
04197     if (tmpbuf[0] == 0x15) /* ACK */
04198     {
04199         frame[0] = 0x06;
04200         return 1;
04201     }
04202 
04203     if (tmpbuf[0] == 0x02)
04204     {
04205         p = &tmpbuf[nn];
04206         n = pdv_serial_wait(pdv_p, 50, len);
04207         pdv_serial_read(pdv_p, p, n);
04208         /* ALERT -- FINISH this! */
04209     }
04210     return n;
04211 }
04212 
04228 int
04229 pdv_send_duncan_frame(PdvDev * pdv_p, u_char *cmdbuf, int size)
04230 {
04231     int i;
04232     u_char frame[128];
04233     u_char *p = frame;
04234 
04235     *p++ = 0x02;
04236     for (i=0; i<size; i++)
04237         *p++ = cmdbuf[i];
04238 
04239     CheckSumMessage(frame);
04240 
04241     return pdv_serial_binary_command_flagged(pdv_p, (char *)frame, size+2, 0);
04242 }
04243 
04244 static void
04245 CheckSumMessage(unsigned char *msg)
04246 {
04247     unsigned short length; 
04248     unsigned char csum = 0;
04249 
04250     msg++;         
04251     length = *msg++;
04252     length += *msg++ << 8;
04253     if (length > 0)
04254     {
04255         for (; length > 0; length--)
04256             csum += *msg++;
04257         *msg = -csum;
04258     }
04259 }
04260 
04261 
04274 int
04275 pdv_read_duncan_frame(PdvDev * pdv_p, u_char *frame)
04276 {
04277     int n, nn;
04278     u_short length;
04279 
04280     /* read the STX and 2-byte length */
04281     n = pdv_serial_wait(pdv_p, 500, 3);
04282     if (n < 3)
04283         return 0;
04284 
04285     nn = pdv_serial_read(pdv_p, (char *)frame, 3);
04286 
04287     length = (u_short)frame[1] + (u_short)(frame[2] << 8);
04288 
04289     if (length)
04290         n = pdv_serial_wait(pdv_p, 1000, length+1);
04291 
04292     if (n)
04293         pdv_serial_read(pdv_p, (char *)(&frame[3]), n);
04294 
04295     return n+nn;
04296 }
04297 
04321 int
04322 pdv_serial_binary_command_flagged(PdvDev * pdv_p, const char *cmd, int len, u_int flag)
04323 {
04324     char    *buf;
04325     int     ret;
04326     int     i;
04327     int     tmplen = 0;
04328 
04329     edt_msg(DBG2, "pdv_serial_binary_command()\n");
04330 
04331     if (pdv_p == NULL || pdv_p->dd_p == NULL)
04332         return -1;
04333 
04334     if ((buf = (char *)malloc(len)) == NULL)
04335         return -1;
04336 
04337     /* prepend "c" for FOI */
04338     if (pdv_p->devid == PDVFOI_ID)
04339     {
04340         buf[tmplen++] = 'c';
04341         if (flag & SCFLAG_NORESP)
04342             buf[tmplen++] = 't';
04343         buf[tmplen++] = ' ';
04344     }
04345 
04346     /* don't include CR or LF */
04347     for (i = 0; i < len; i++)
04348     {
04349         buf[tmplen++] = cmd[i];
04350     }
04351     ret = pdv_serial_write(pdv_p, buf, tmplen);
04352 
04353     free(buf);
04354     return (ret);
04355 }
04356  /* end serial */
04358 
04387 int
04388 pdv_read(PdvDev * pdv_p, unsigned char *buf, unsigned long size)
04389 {
04390     Dependent *dd_p;
04391     unsigned long newsize;
04392     int     readsize;
04393     unsigned char *tbuf;
04394 
04395 
04396     edt_msg(DBG2, "pdv_read(%d)\n", size);
04397 
04398     pdv_setup_dma(pdv_p);
04399 
04400     if (pdv_p->dd_p->start_delay)
04401         edt_msleep(pdv_p->dd_p->start_delay);
04402 
04403 
04404     if (pdv_specinst_serial_triggered(pdv_p))
04405     {
04406         edt_msg(PDVWARN, "libpdv invalid combination: SPECINST_SERIAL/pdv_read/i/f trigger");
04407         edt_msg(PDVWARN, "should use pdv_start_image() or external trigger");
04408     }
04409 
04410     if (pdv_p == NULL || pdv_p->dd_p == NULL)
04411         return -1;
04412 
04413     dd_p = pdv_p->dd_p;
04414 
04415     if (pdv_p->devid == DMY_ID)
04416     {
04417         pdv_dmy_data(buf, dd_p->width, dd_p->height, dd_p->depth);
04418         if (dd_p->markras)
04419             pdv_mark_ras(buf, dd_p->rascnt,
04420             dd_p->width, dd_p->height, dd_p->markrasx, dd_p->markrasy);
04421         if (dd_p->markbin)
04422             pdv_mark_bin(buf, dd_p->rascnt, dd_p->width, dd_p->height, 4, 0);
04423         if (dd_p->markbin || dd_p->markras) dd_p->rascnt++ ;
04424         printf("pdv_read rascnt %d\n",dd_p->rascnt) ;
04425         return (size);
04426     }
04427 
04428     readsize = pdv_get_dmasize(pdv_p);
04429 
04430     if (dd_p->swinterlace)
04431         pdv_alloc_tmpbuf(pdv_p);
04432 
04433     /*
04434     * specify register and value to set after starting dma
04435     */
04436     edt_startdma_reg(pdv_p, PDV_CMD, PDV_ENABLE_GRAB);
04437     if (edt_get_firstflush(pdv_p) != EDT_ACT_KBS)
04438         edt_set_firstflush(pdv_p, EDT_ACT_ONCE);
04439 
04440 
04441     if (dd_p->slop)
04442     {
04443         edt_msg(DBG2, "adjusting readsize %x by slop %x to %x\n",
04444             readsize, dd_p->slop, readsize - dd_p->slop);
04445         readsize -= dd_p->slop;
04446     }
04447 
04448     if (dd_p->swinterlace)
04449     {
04450         if (pdv_process_inplace(pdv_p))
04451             tbuf = buf;
04452         else
04453             tbuf = pdv_p->tmpbuf;
04454 
04455         newsize = edt_read(pdv_p, tbuf, readsize);
04456         dd_p->last_raw = tbuf;
04457         dd_p->last_image = buf;
04458     }
04459     else
04460     {
04461         tbuf = buf;
04462         newsize = edt_read(pdv_p, buf, readsize);
04463         dd_p->last_raw = buf;
04464         dd_p->last_image = buf;
04465     }
04466 
04467     dd_p->rascnt = 1;
04468     if (dd_p->markras)
04469         pdv_mark_ras(buf, dd_p->rascnt++, dd_p->width, dd_p->height,
04470         dd_p->markrasx, dd_p->markrasy);
04471 
04472     size = newsize;
04473 
04474     /* edt_startdma_reg(pdv_p, 0, 0) ; */
04475 
04476     edt_msg(DBG2, "swinterlace %d\n", dd_p->swinterlace);
04477 
04478     pdv_deinterlace(pdv_p, dd_p, tbuf, buf);
04479 
04480     return (size);
04481 }
04482 
04483 
04502 unsigned char *
04503 pdv_image(PdvDev * pdv_p)
04504 {
04505     edt_msg(DBG2, "pdv_image()\n");
04506 
04507     pdv_start_images(pdv_p, 1);
04508     return pdv_wait_images(pdv_p, 1);
04509 }
04510 
04511 
04522 unsigned char *
04523 pdv_image_raw(PdvDev * pdv_p)
04524 {
04525     edt_msg(DBG2, "pdv_image()\n");
04526 
04527     pdv_start_images(pdv_p, 1);
04528     return pdv_wait_images_raw(pdv_p, 1);
04529 }
04530 
04539 void
04540 pdv_start_image(PdvDev * pdv_p)
04541 {
04542     edt_msg(DBG2, "pdv_start_image()\n");
04543 
04544     pdv_start_images(pdv_p, 1);
04545 }
04546 
04547 
04560 void
04561 pdv_start_images(PdvDev * pdv_p, int count)
04562 {
04563 
04564     edt_msg(DBG2, "pdv_start_images(%d) %d\n", count, pdv_p->dd_p->started_continuous);
04565 
04566     if (pdv_p->dd_p->start_delay)
04567         edt_msleep(pdv_p->dd_p->start_delay);
04568 
04569     /* automatically alloc 1 buffer if none allocated */
04570     if (pdv_p->ring_buffer_numbufs < 1)
04571         pdv_multibuf(pdv_p, 1);
04572 
04573     /* 
04574     if (pdv_p->devid == DMY_ID)
04575     {
04576     dmystarted += count ;
04577     return;
04578     }
04579     */
04580     if (!pdv_p->dd_p->started_continuous)
04581     {
04582         pdv_setup_continuous(pdv_p);
04583     }
04584     if (pdv_force_single(pdv_p) && (count > 1))
04585     {
04586         edt_msg(PDVWARN,
04587             "pdv_start_images(): %d buffers requested; should only\n", count);
04588         edt_msg(PDVWARN,
04589             "start one at a time when 'force_single' is set in config file\n");
04590         count = 1;
04591     }
04592 
04593 
04594     edt_start_buffers(pdv_p, count);
04595 
04596     if (pdv_specinst_serial_triggered(pdv_p))
04597         pdv_trigger_specinst(pdv_p);
04598 }
04599 
04600 
04642 unsigned char *
04643 pdv_wait_image(PdvDev * pdv_p)
04644 {
04645     edt_msg(DBG2, "pdv_wait_image()\n");
04646 
04647     return pdv_wait_images(pdv_p, 1);
04648 }
04649 
04681 unsigned char *
04682 pdv_wait_image_raw(PdvDev * pdv_p)
04683 {
04684     edt_msg(DBG2, "pdv_wait_image()\n");
04685 
04686     return pdv_wait_images_raw(pdv_p, 1);
04687 }
04688 
04689 
04729 unsigned char *
04730 pdv_wait_image_timed(PdvDev * pdv_p, u_int * timep)
04731 {
04732     return pdv_wait_image_timed_raw(pdv_p, timep, FALSE);
04733 }
04734 
04775 unsigned char *
04776 pdv_wait_image_timed_raw(PdvDev * pdv_p, u_int * timep, int doRaw)
04777 {
04778     u_char *ret;
04779 
04780     edt_msg(DBG2, "pdv_wait_image()\n");
04781 
04782     if (doRaw)
04783         ret = pdv_wait_images_raw(pdv_p, 1);
04784     else
04785         ret = pdv_wait_images(pdv_p, 1);
04786 
04787     edt_get_timestamp(pdv_p, timep, pdv_p->donecount - 1);
04788     return (ret);
04789 }
04790 
04837 unsigned char *
04838 pdv_wait_images_timed_raw(PdvDev * pdv_p, int count, u_int * timep, int doRaw)
04839 {
04840     u_char *ret;
04841 
04842     edt_msg(DBG2, "pdv_wait_images_timed_raw(count=%d, doRaw=%d)\n", count, doRaw);
04843     if (doRaw)
04844         ret = pdv_wait_images_raw(pdv_p, count);
04845     else
04846         ret = pdv_wait_images(pdv_p, count);
04847 
04848     edt_get_timestamp(pdv_p, timep, pdv_p->donecount - 1);
04849     return (ret);
04850 }
04851 
04880 unsigned char *
04881 pdv_wait_images_timed(PdvDev * pdv_p, int count, u_int * timep)
04882 {
04883     return pdv_wait_images_timed_raw(pdv_p, count, timep, FALSE);
04884 }
04885 
04890 unsigned char *
04891 pdv_last_image_timed_raw(PdvDev * pdv_p, u_int * timep, int doRaw)
04892 {
04893     return pdv_wait_last_image_timed_raw(pdv_p, timep, doRaw);
04894 
04895 }
04896 
04927 unsigned char *
04928 pdv_wait_last_image_timed_raw(PdvDev * pdv_p, u_int * timep, int doRaw)
04929 {
04930     u_char *ret;
04931     int     donecount;
04932     int     last_wait;
04933     int     delta;
04934 
04935     donecount = edt_done_count(pdv_p);
04936     last_wait = pdv_p->donecount;
04937 
04938     edt_msg(DBG2, "pdv_wait_last_image_timed() last %d cur %d\n",
04939         last_wait, donecount);
04940 
04941     delta = donecount - last_wait;
04942 
04943     if (delta == 0)
04944         delta = 1;
04945 
04946     if (doRaw)
04947         ret = pdv_wait_images_raw(pdv_p, delta);
04948     else
04949         ret = pdv_wait_images(pdv_p, delta);
04950 
04951     edt_get_timestamp(pdv_p, timep, pdv_p->donecount - 1);
04952     return (ret);
04953 }
04954 
04978 unsigned char *
04979 pdv_wait_last_image_timed(PdvDev * pdv_p, u_int * timep)
04980 {
04981     return pdv_wait_last_image_timed_raw(pdv_p, timep, FALSE);
04982 }
04983 
04988 unsigned char *
04989 pdv_last_image_timed(PdvDev * pdv_p, u_int * timep)
04990 {
04991 
04992     return pdv_last_image_timed_raw(pdv_p, timep, FALSE);
04993 }
04994 
05015 unsigned char *
05016 pdv_wait_last_image_raw(PdvDev * pdv_p, int *nSkipped, int doRaw)
05017 {
05018     u_char *ret;
05019     int     donecount;
05020     int     last_wait;
05021     int     delta;
05022 
05023     donecount = edt_done_count(pdv_p);
05024     last_wait = pdv_p->donecount;
05025 
05026     edt_msg(DBG2, "pdv_wait_last_image() last %d cur %d\n",
05027         last_wait, donecount);
05028 
05029     delta = donecount - last_wait;
05030 
05031     if (nSkipped)
05032         *nSkipped = (delta) ? delta - 1 : 0;
05033 
05034     if (delta == 0)
05035         delta = 1;
05036 
05037     if (doRaw)
05038         ret = pdv_wait_images_raw(pdv_p, delta);
05039     else
05040         ret = pdv_wait_images(pdv_p, delta);
05041 
05042     return (ret);
05043 }
05044 
05073 unsigned char *
05074 pdv_wait_last_image(PdvDev * pdv_p, int *nSkipped)
05075 {
05076     return pdv_wait_last_image_raw(pdv_p, nSkipped, FALSE);
05077 }
05078 
05099 unsigned char *
05100 pdv_wait_next_image_raw(PdvDev * pdv_p, int *nSkipped, int doRaw)
05101 {
05102     u_char *ret;
05103     int     donecount;
05104     int     last_wait;
05105     int     delta;
05106 
05107     donecount = edt_done_count(pdv_p);
05108     last_wait = pdv_p->donecount;
05109 
05110     edt_msg(DBG2, "pdv_wait_last_image() last %d cur %d\n",
05111         last_wait, donecount);
05112 
05113     delta = donecount - last_wait;
05114 
05115     if (*nSkipped)
05116         *nSkipped = (delta) ? delta - 1 : 0;
05117 
05118 
05119     if (delta == 0)
05120         delta = 1;
05121 
05122     delta++;
05123 
05124     if (doRaw)
05125         ret = pdv_wait_images_raw(pdv_p, delta);
05126     else
05127         ret = pdv_wait_images(pdv_p, delta);
05128 
05129     return (ret);
05130 }
05131 
05147 unsigned char *
05148 pdv_wait_next_image(PdvDev * pdv_p, int *nSkipped)
05149 {
05150 
05151     return pdv_wait_next_image_raw(pdv_p, nSkipped, FALSE);
05152 }
05153 
05154 
05164 int
05165 pdv_in_continuous(PdvDev * pdv_p)
05166 {
05167     edt_msg(DBG2, "pdv_in_continuous() %x\n",
05168         pdv_p->dd_p->continuous);
05169     return pdv_p->dd_p->continuous;
05170 }
05171  /* end acquisition */
05173 
05174 void
05175 pdv_check(PdvDev * pdv_p)
05176 {
05177     int     stat;
05178     int     overrun;
05179 
05180     stat = edt_reg_read(pdv_p, PDV_STAT);
05181     overrun = edt_ring_buffer_overrun(pdv_p);
05182     edt_msg(DBG2, "pdv_check() stat %x overrun %x\n",
05183         stat, overrun);
05184     if ((stat & PDV_OVERRUN) || overrun)
05185     {
05186         if (pdv_p->dd_p->continuous)
05187             pdv_stop_hardware_continuous(pdv_p);
05188 
05189         pdv_flush_fifo(pdv_p);
05190 
05191         pdv_multibuf(pdv_p, pdv_p->ring_buffer_numbufs);
05192 
05193         if (pdv_p->dd_p->continuous)
05194             pdv_start_hardware_continuous(pdv_p);
05195     }
05196 }
05197 
05198 void
05199 pdv_checkfrm(PdvDev * pdv_p, u_short * imagebuf, u_int imagesize, int verbose)
05200 {
05201     u_short *tmpp;
05202 
05203     for (tmpp = (u_short *) imagebuf;
05204         tmpp < (u_short *) (&imagebuf[imagesize]); tmpp++)
05205     {
05206         if (*tmpp & 0xf000)
05207         {
05208             edt_msg(DBG2, "found start of image %x at %x %d\n",
05209                 *tmpp >> 12,
05210                 tmpp - (u_short *) imagebuf,
05211                 tmpp - (u_short *) imagebuf);
05212             if (tmpp != imagebuf)
05213             {
05214                 int     curdone;
05215                 int     curtodo;
05216 
05217                 edt_reg_write(pdv_p, PDV_CMD, PDV_RESET_INTFC);
05218                 pdv_flush_fifo(pdv_p);
05219                 curdone = edt_done_count(pdv_p);
05220                 curtodo = edt_get_todo(pdv_p);
05221                 edt_msg(DBG2, "done %d todo %d\n", curdone, curtodo);
05222                 {
05223                     pdv_stop_continuous(pdv_p);
05224                     edt_set_buffer(pdv_p, curdone);
05225                     pdv_setup_continuous(pdv_p);
05226                     pdv_start_images(pdv_p, pdv_p->ring_buffer_numbufs -
05227                         (curtodo - curdone));
05228                 }
05229             }
05230             break;
05231         }
05232     }
05233 }
05234 
05235 u_char *
05236 pdv_get_interleave_data(PdvDev *pdv_p, u_char *buf)
05237 
05238 {
05239     if (!pdv_process_inplace(pdv_p))
05240     {
05241         return  buf + pdv_get_dmasize(pdv_p);
05242     }
05243     else
05244         return buf;
05245 }
05246 
05247 
05274 unsigned char *
05275 pdv_wait_images_raw(PdvDev * pdv_p, int count)
05276 {
05277     u_char *buf;
05278     Dependent *dd_p;
05279     static int last_timeout = 0;
05280 
05281     edt_msg(DBG2, "pdv_wait_images_raw(%d)\n", count);
05282 
05283     if (pdv_p == NULL || pdv_p->dd_p == NULL)
05284         return NULL;
05285 
05286     dd_p = pdv_p->dd_p;
05287 
05288     if (pdv_specinst_serial_triggered(pdv_p))
05289         pdv_posttrigger_specinst(pdv_p);
05290 
05291     if (pdv_p->devid == DMY_ID)
05292     {
05293         u_char *buf;
05294         u_int  *tmpp;
05295 
05296         buf = edt_next_writebuf(pdv_p);
05297         tmpp = (u_int *) buf;
05298         if (*tmpp != 0xaabbccdd)
05299         {
05300             pdv_dmy_data(buf, dd_p->width, dd_p->height, dd_p->depth);
05301         }
05302         *tmpp = 0xaabbccdd;
05303         dd_p->last_image = buf;
05304         dd_p->last_raw = buf;
05305         if (dd_p->markras)
05306             pdv_mark_ras(buf, dd_p->rascnt, dd_p->width, dd_p->height,
05307             dd_p->markrasx, dd_p->markrasy);
05308         if (dd_p->markbin)
05309             pdv_mark_bin(buf, dd_p->rascnt, dd_p->width, dd_p->height, 4, 0);
05310 
05311         if (dd_p->markbin || dd_p->markras) dd_p->rascnt++ ;
05312         return (buf);
05313     }
05314 
05315 
05316     last_timeout = edt_timeouts(pdv_p);
05317     buf = edt_wait_for_buffers(pdv_p, count);
05318 
05319     return buf;
05320 
05321 
05322 }
05323 
05324 
05370 u_char *
05371 pdv_wait_images(PdvDev *pdv_p, int count)
05372 
05373 {
05374     u_char *buf;
05375     u_char *retval;
05376     Dependent *dd_p;
05377 
05378     edt_msg(DBG2, "pdv_wait_images(%d)\n", count);
05379 
05380     if (pdv_p == NULL || pdv_p->dd_p == NULL)
05381         return NULL;
05382 
05383     dd_p = pdv_p->dd_p;
05384 
05385     if (dd_p->swinterlace)
05386     {
05387         pdv_alloc_tmpbuf(pdv_p);        
05388     }
05389 
05390     buf = pdv_wait_images_raw(pdv_p, count);
05391 
05392     if (dd_p->swinterlace)
05393     {
05394 
05395         if (!pdv_process_inplace(pdv_p))
05396         {
05397             retval = buf + pdv_get_dmasize(pdv_p);
05398         }
05399         else
05400             retval = buf;
05401 
05402         pdv_deinterlace(pdv_p, dd_p, buf, retval);
05403 
05404         dd_p->last_raw = buf;
05405         dd_p->last_image = retval;
05406     }
05407     else
05408     {
05409         retval = buf;
05410         dd_p->last_raw = buf;
05411         dd_p->last_image = buf;
05412     }
05413 
05414     /* problem is that pdv_flshow calling images_raw directly - talk to steve */
05415     if (pdv_p->devid != DMY_ID)
05416     {
05417         if (dd_p->markras)
05418             pdv_mark_ras(buf, dd_p->rascnt, dd_p->width, dd_p->height,
05419             dd_p->markrasx, dd_p->markrasy);
05420         if (dd_p->markbin)
05421             pdv_mark_bin(buf, dd_p->rascnt, dd_p->width, dd_p->height, 4, 0);
05422 
05423         if (dd_p->markbin || dd_p->markras) dd_p->rascnt++ ;
05424     }
05425 
05426 
05427     return (retval);
05428 }
05429 
05430 int
05431 pdv_slop(PdvDev * pdv_p)
05432 {
05433     return (pdv_p->dd_p->slop);
05434 }
05435 
05436 
05437 int
05438 pdv_set_slop(PdvDev * pdv_p, int slop)
05439 {
05440     edt_msg(DBG2, "pdv_set_slop()\n");
05441 
05442     pdv_p->dd_p->slop = slop;
05443     return (0);
05444 }
05445 
05446 
05486 pdv_set_header_type(PdvDev *pdv_p, int header_type, int irig_slave, int irig_offset, int irig_raw)
05487 {
05488     if (!((pdv_p->devid ==  PE8DVCL_ID)
05489      || (pdv_p->devid == PE8DVFOX_ID))) /* anticipated */
05490         return -1;
05491 
05492     edt_reg_and(pdv_p, PDV_UTILITY, ~(PDV_ENFRMCNT|PDVCL_IRIG2));
05493 
05494     switch(header_type)
05495     {
05496         case HDR_TYPE_IRIG2:
05497             pdv_p->dd_p->header_position = HeaderEnd;
05498             pdv_p->dd_p->header_size = 32;
05499             pdv_p->dd_p->header_dma = 1;
05500             edt_reg_or(pdv_p, PDV_UTILITY, PDVCL_IRIG2); /* just toggled off then back on resets */
05501             pdv_p->spi_reg_base = PDV_IRIG_SPI_BASE;
05502 
05503             pdv_irig_set_slave(pdv_p, irig_slave);
05504             if (!irig_slave)
05505             {
05506                 pdv_irig_set_offset(pdv_p, irig_offset);
05507                 pdv_irig_set_bcd(pdv_p, irig_raw);
05508             }
05509             pdv_p->dd_p->header_type = header_type;
05510 
05511             break;
05512         default:
05513             return -1;
05514     }
05515 
05516     edt_set_dependent(pdv_p, pdv_p->dd_p);
05517 
05518     return 0;
05519 }
05520 
05533 int
05534 pdv_get_header_size(PdvDev * pdv_p)
05535 {
05536     return (pdv_p->dd_p->header_size);
05537 }
05538 
05564 HdrPosition
05565 pdv_get_header_position(PdvDev * pdv_p)
05566 {
05567     return (HdrPosition) (pdv_p->dd_p->header_position);
05568 }
05569 
05586 int
05587 pdv_get_header_offset(PdvDev * pdv_p)
05588 {
05589     switch (pdv_p->dd_p->header_position)
05590     {
05591     case HeaderBefore:
05592         pdv_p->dd_p->header_offset = - (int) pdv_p->dd_p->header_size;
05593         break;
05594     case HeaderBegin:
05595         pdv_p->dd_p->header_offset = 0;
05596         break;
05597     case HeaderEnd:
05598         pdv_p->dd_p->header_offset = pdv_get_dmasize(pdv_p) - pdv_p->dd_p->header_size ;
05599         break;
05600     case HeaderAfter:
05601         pdv_p->dd_p->header_offset = pdv_p->dd_p->imagesize;
05602         break;
05603 
05604     }
05605 
05606     return (pdv_p->dd_p->header_offset);
05607 }
05608 
05617 int
05618 pdv_get_header_dma(PdvDev * pdv_p)
05619 {
05620     return (pdv_p->dd_p->header_dma);
05621 }
05622 
05623 int
05624 pdv_get_header_within(PdvDev *pdv_p)
05625 
05626 {
05627     return (pdv_p->dd_p->header_position == HeaderBegin ||
05628         pdv_p->dd_p->header_position == HeaderMiddle ||
05629         pdv_p->dd_p->header_position == HeaderEnd);
05630 }
05631 
05641 int
05642 pdv_extra_headersize(PdvDev * pdv_p)
05643 
05644 {
05645     if (pdv_p->dd_p->header_size && (!pdv_p->dd_p->header_dma) &&
05646         (pdv_p->dd_p->header_position ==  HeaderBefore || 
05647         pdv_p->dd_p->header_position == HeaderAfter))
05648         return pdv_p->dd_p->header_size;
05649 
05650     return 0;
05651 }
05652 
05662 void
05663 pdv_set_header_size(PdvDev * pdv_p, int header_size)
05664 {
05665     edt_msg(DBG2, "pdv_set_header_size()\n");
05666 
05667     pdv_p->dd_p->header_size = header_size;
05668 
05669 }
05670 
05690 void
05691 pdv_set_header_position(PdvDev * pdv_p, HdrPosition header_position)
05692 
05693 {
05694     edt_msg(DBG2, "pdv_set_header_position(%d)\n", header_position);
05695 
05696     pdv_p->dd_p->header_position = header_position;
05697 }
05698 
05708 void
05709 pdv_set_header_dma(PdvDev * pdv_p, int header_dma)
05710 {
05711     edt_msg(DBG2, "pdv_set_header_dma(%d,%d)\n", header_dma);
05712 
05713     pdv_p->dd_p->header_dma = header_dma;
05714 }
05715 
05716 
05723 void
05724 pdv_set_header_offset(PdvDev * pdv_p, int header_offset)
05725 
05726 {
05727     edt_msg(DBG2, "pdv_set_header_offset(%d,%d)\n", header_offset);
05728 
05729     pdv_p->dd_p->header_offset = header_offset;
05730 }
05731  /* end settings */
05733 
05758 int
05759 pdv_shutter_method(PdvDev * pdv_p)
05760 {
05761     edt_msg(DBG2, "pdv_shutter_method()\n");
05762 
05763     return pdv_p->dd_p->camera_shutter_timing;
05764 }
05765 
05773 void
05774 pdv_set_interlace(PdvDev * pdv_p, int interlace)
05775 {
05776     edt_msg(DBG2, "pdv_set_interlace()\n");
05777 
05778     pdv_p->dd_p->swinterlace = interlace;
05779 
05780     pdv_setup_postproc(pdv_p, pdv_p->dd_p, NULL);
05781 
05782 }
05783 
05841 int
05842 pdv_interlace_method(PdvDev * pdv_p)
05843 {
05844     edt_msg(DBG2, "pdv_interlace_method()\n");
05845 
05846     return pdv_p->dd_p->swinterlace;
05847 }
05848 
05849 
05866 int
05867 pdv_debug(int flag)
05868 {
05869     int     oldval = Pdv_debug;
05870 
05871     edt_msg(DBG2, "pdv_debug()\n");
05872 
05873     Pdv_debug = flag;
05874     return (oldval);
05875 }
05876 
05885 int
05886 pdv_debug_level()
05887 {
05888     return Pdv_debug;
05889 }
05890 
05891 
05903 int
05904 pdv_overrun(PdvDev * pdv_p)
05905 {
05906     int     overrun;
05907 
05908     edt_msg(DBG2, "pdv_overrun()\n");
05909 
05910     if (pdv_p->devid == DMY_ID)
05911         return (0);
05912     edt_ioctl(pdv_p, EDTG_OVERFLOW, &overrun);
05913     return (overrun);
05914 }
05915 
05934 int
05935 pdv_serial_wait(PdvDev * pdv_p, int msecs, int count)
05936 {
05937     edt_buf tmp;
05938     int     ret;
05939 
05940     if (msecs == 0)
05941         msecs = pdv_p->dd_p->serial_timeout;
05942 
05943     tmp.desc = msecs;
05944     tmp.value = count;
05945     edt_ioctl(pdv_p, EDTS_SERIALWAIT, &tmp);
05946     ret = (int) tmp.value;
05947     edt_msg(DBG2, "pdv_serial_wait(%d, %d) %d\n", msecs, count, ret);
05948     return (ret);
05949 }
05950 
05963 int
05964 pdv_serial_get_numbytes(PdvDev * pdv_p)
05965 {
05966     edt_buf tmp;
05967     int     ret;
05968 
05969     tmp.desc = 0;
05970     tmp.value = 0;
05971     edt_ioctl(pdv_p, EDTS_SERIALWAIT, &tmp);
05972     ret = (int) tmp.value;
05973     edt_msg(DBG2, "pdv_serial_get_numbytes %d\n", ret);
05974     return (ret);
05975 }
05976 
05990 int
05991 pdv_serial_wait_next(EdtDev * pdv_p, int msecs, int count)
05992 {
05993     int     ret;
05994     int     newcount = count;
05995 
05996     if (pdv_p->devid == PDVFOI_ID)
05997     {
05998         if (newcount)
05999             newcount += 2;
06000         ret = pdv_serial_wait(pdv_p, msecs, newcount);
06001         if (ret >= 2)
06002             ret -= 2;
06003     }
06004     else
06005         ret = pdv_serial_wait(pdv_p, msecs, count);
06006     return (ret);
06007 }
06008 
06026 int
06027 pdv_set_waitchar(PdvDev * pdv_p, int enable, u_char wchar)
06028 {
06029     edt_buf tmp;
06030     int     ret;
06031 
06032 
06033     tmp.desc = enable;
06034     tmp.value = wchar;
06035     ret = edt_ioctl(pdv_p, EDTS_WAITCHAR, &tmp);
06036     pdv_p->dd_p->serial_waitc = wchar;
06037     if (!enable) /* top bit is flag for disabled (internally) */
06038         pdv_p->dd_p->serial_waitc |= 0x100;
06039     edt_msg(DBG2, "pdv_set_waitchar(%d, %02x) returns %d\n", enable, wchar, ret);
06040     return (ret);
06041 }
06042 
06055 int
06056 pdv_get_waitchar(PdvDev * pdv_p, u_char *waitc)
06057 {
06058     int ret;
06059 
06060     if (pdv_p->dd_p->serial_waitc & 0x100)
06061     {
06062         *waitc = pdv_p->dd_p->serial_waitc & 0xff;
06063         ret = 0;
06064     }
06065     else
06066     {
06067         *waitc = pdv_p->dd_p->serial_waitc;
06068         ret = 1;
06069     }
06070     return ret;
06071 }
06072 
06073 
06074 int
06075 pdv_get_fulldma_size(PdvDev *pdv_p, int *extrasizep)
06076 
06077 {
06078     int     size = pdv_get_imagesize(pdv_p);
06079 
06080     int     slop = pdv_slop(pdv_p);
06081     int     extrasize;
06082     Dependent *dd_p = pdv_p->dd_p;
06083 
06084     extrasize = slop + pdv_extra_headersize(pdv_p);
06085 
06086     if (pdv_get_header_dma(pdv_p) && (pdv_get_header_within(pdv_p)))
06087 
06088         size += pdv_get_header_size(pdv_p);
06089 
06090     if (dd_p->swinterlace || size != pdv_get_dmasize(pdv_p))
06091     {
06092         /* If extra buffer needed, put it after the data */
06093 
06094         if (!pdv_process_inplace(pdv_p) || size != pdv_get_dmasize(pdv_p))
06095         {
06096             int     newsize = pdv_get_dmasize(pdv_p);
06097 
06098             extrasize += size;  /* use second part of buffer for interlace result */
06099             size = newsize;
06100         }
06101     }
06102 
06103     if (extrasizep)
06104         *extrasizep = extrasize;
06105 
06106     return size;
06107 }
06108 
06109 int
06110 pdv_total_block_size(PdvDev *pdv_p, int numbufs)
06111 
06112 {
06113     int extrasize = 0;
06114     int size;
06115 
06116     size = pdv_get_fulldma_size(pdv_p, &extrasize);
06117 
06118     /* round up */
06119     size = edt_get_total_bufsize(pdv_p, size,extrasize) * numbufs;
06120 
06121     return size;
06122 
06123 }
06124 
06125 int
06126 pdv_multibuf_block(PdvDev *pdv_p, int numbufs, u_char *block, int blocksize)
06127 
06128 {
06129     int size, extrasize;
06130     int ret;
06131     int header_before = (pdv_p->dd_p->header_position == HeaderBefore);
06132 
06133     size = pdv_get_fulldma_size(pdv_p, &extrasize);
06134 
06135     pdv_setup_dma(pdv_p);
06136 
06137     ret = edt_configure_block_buffers_mem(pdv_p, 
06138         size, 
06139         numbufs, 
06140         EDT_READ, 
06141         extrasize, 
06142         header_before,
06143         block) ;
06144 
06145 
06146     return ret;
06147 
06148 }
06149 
06150 int
06151 pdv_multibuf_separate(PdvDev *pdv_p, int numbufs, u_char **buffers)
06152 
06153 {
06154     int     size = pdv_get_imagesize(pdv_p);
06155     int ret;
06156 
06157     Dependent *dd_p = pdv_p->dd_p;
06158 
06159     if (dd_p->swinterlace || size != pdv_get_dmasize(pdv_p))
06160     {
06161         /* If extra buffer needed, put it after the data */
06162 
06163         if (!pdv_process_inplace(pdv_p) || size != pdv_get_dmasize(pdv_p))
06164         {
06165             edt_msg_perror(PDVFATAL,"Interlace not inplace fails for multibuf_separate\n");
06166             return -1;
06167         }
06168     }
06169 
06170     size = pdv_get_fulldma_size(pdv_p, NULL);
06171 
06172     pdv_setup_dma(pdv_p);
06173 
06174     ret = edt_configure_ring_buffers(pdv_p, size, numbufs, EDT_READ, buffers) ;
06175 
06176     return ret;
06177 
06178 }
06179 
06204 int
06205 pdv_multibuf(PdvDev * pdv_p, int numbufs)
06206 {
06207     /* set number of buffers, library allocated. */
06208 
06209     /* define if not enough memory for contiguous allocation */
06210     /* but beware of interlace since currently not supported in separate */
06211     /* #ifdef RADSTONE*/
06212 #if defined(XCALIBURCOMMON) || defined(VMIC)
06213     return pdv_multibuf_separate(pdv_p, numbufs,NULL);
06214 #else
06215     return pdv_multibuf_block(pdv_p, numbufs, NULL, 0);
06216 #endif
06217 
06218 }
06219 
06260 int
06261 pdv_set_buffers(PdvDev * pdv_p, int numbufs, unsigned char **bufarray)
06262 {
06263     /* set number of buffers, user allocated. */
06264     int     size = pdv_get_dmasize(pdv_p);
06265 
06266     edt_msg(DBG2, "pdv_set_buffers(%d %x) (size %d)\n", numbufs, bufarray, size);
06267 
06268     pdv_setup_dma(pdv_p);
06269 
06270     return (edt_configure_ring_buffers(pdv_p, size, numbufs, EDT_READ, bufarray));
06271 }
06272 
06273 /* plus size - so far just used for merge */
06274 int
06275 pdv_set_buffers_x(PdvDev * pdv_p, int numbufs, int size, unsigned char **bufs)
06276 {
06277 
06278     edt_msg(DBG2, "pdv_set_buffers(%d %x) (size %d)\n", numbufs, bufs, size);
06279 
06280     pdv_setup_dma(pdv_p);
06281 
06282     return (edt_configure_ring_buffers(pdv_p, size, numbufs, EDT_READ, bufs));
06283 }
06284 
06285 
06300 int
06301 pdv_image_size(PdvDev * pdv_p)
06302 {
06303     int     size;
06304 
06305     size = pdv_p->dd_p->imagesize;
06306 
06307     if (pdv_p->dd_p->slop)
06308     {
06309 
06310         edt_msg(DBG2, "pdv_image_size: adjusting size %x by slop %x to %x\n",
06311             size, pdv_p->dd_p->slop, size - pdv_p->dd_p->slop);
06312 
06313         size -= pdv_p->dd_p->slop;
06314 
06315     }
06316 
06317     if (pdv_p->dd_p->header_dma)
06318         size += pdv_p->dd_p->header_size;
06319 
06320     edt_msg(DBG2, "pdv_image_size() %d\n", size);
06321 
06322     return size;
06323 
06324 }
06325 
06326 
06340 u_char *
06341 pdv_get_last_image(PdvDev * pdv_p)
06342 {
06343     edt_msg(DBG2, "pdv_get_last_image()\n");
06344 
06345     return (pdv_p->dd_p->last_image);
06346 }
06347 
06362 u_char *
06363 pdv_get_last_raw(PdvDev * pdv_p)
06364 {
06365     edt_msg(DBG2, "pdv_get_last_raw()\n");
06366 
06367     return (pdv_p->dd_p->last_raw);
06368 }
06369 
06384 u_char **
06385 pdv_buffer_addresses(PdvDev * pdv_p)
06386 {
06387     /* (same as edt_buffer_addresses) */
06388     return (pdv_p->ring_buffers);
06389 }
06390 
06416 void
06417 pdv_start_hardware_continuous(PdvDev * pdv_p /* , int frames */ )
06418 {
06419     int     data_path;
06420 
06421     /* data_path = edt_reg_read(pdv_p, PDV_DATA_PATH); */
06422     data_path = pdv_p->dd_p->datapath_reg & ~PDV_CONTINUOUS;
06423     /* data_path = 0x5 ; */
06424     edt_msg(DBG2, "pdv_start_hardware_continuous()\n");
06425 
06426     if (pdv_p->devid == PDVFOI_ID)
06427     {
06428         char    tmpbuf[10];
06429         int     ret;
06430 
06431         ret = pdv_serial_wait(pdv_p, 100, 0);
06432         if (ret > 10)
06433             pdv_reset_serial(pdv_p);
06434         else
06435             pdv_serial_read(pdv_p, tmpbuf, ret);
06436 
06437     }
06438     /* clear first - let driver set */
06439     if (pdv_p->devid == PDVFOI_ID)
06440     {
06441         char    tmpbuf[10];
06442         int     ret;
06443 
06444         ret = pdv_serial_wait(pdv_p, 100, 0);
06445         if (ret > 10)
06446             pdv_reset_serial(pdv_p);
06447         else
06448             pdv_serial_read(pdv_p, tmpbuf, ret);
06449 
06450     }
06451     edt_reg_write(pdv_p, PDV_DATA_PATH, data_path | PDV_CONTINUOUS);
06452     pdv_p->dd_p->datapath_reg = data_path;
06453 }
06454 
06455 
06465 void
06466 pdv_stop_hardware_continuous(PdvDev * pdv_p)
06467 {
06468     int     data_path;
06469 
06470     /* data_path = edt_reg_read(pdv_p, PDV_DATA_PATH); */
06471     data_path = pdv_p->dd_p->datapath_reg;
06472     edt_msg(DBG2, "pdv_stop_hardware_continuous()\n");
06473     data_path &= ~PDV_CONTINUOUS;
06474     edt_reg_write(pdv_p, PDV_DATA_PATH, data_path);
06475     pdv_p->dd_p->datapath_reg = data_path;
06476 
06477     if (pdv_p->devid == PDVFOI_ID)
06478     {
06479         edt_reg_write(pdv_p,FOI_WR_MSG_STAT, FOI_FIFO_FLUSH);
06480     }
06481 
06482 }
06483 
06494 int
06495 pdv_set_serial_parity(PdvDev * pdv_p, char parity)
06496 {
06497     if (pdv_p->devid == PDVAERO_ID)
06498     {
06499         int val = 0;
06500         switch(parity)
06501         {
06502 
06503         case 'e':
06504             val = 1;
06505             break;
06506         case 'o':
06507             val = 3;
06508             break;
06509         case 'n':
06510             val = 0;
06511             break;
06512         default:
06513             edt_msg(DBG1, "parity must be e, o, or n");
06514             return -1;
06515         }
06516 
06517         edt_reg_write(pdv_p,PDV_SERIAL_PARITY,val);
06518         return 0;
06519     }
06520     else
06521     {
06522         edt_msg(DBG1,"parity not an option for this board");
06523     }
06524     return -1;
06525 }
06526 
06542 int
06543 pdv_set_baud(PdvDev * pdv_p, int baud)
06544 {
06545     Dependent *dd_p = pdv_p->dd_p;
06546     u_int   baudbits = 0;
06547     int     id=pdv_p->devid;
06548     u_int   new, baudreg;
06549     u_int   cntl;
06550     int     donew        = 0;
06551     int     ret = 0;
06552 
06553     if (dd_p->xilinx_rev < 2 || dd_p->xilinx_rev > 32)
06554     {
06555         edt_msg(DBG2, "pdv_set_baud() warning: can't enable, N/A this xilinx (%x)\n",
06556             pdv_p->dd_p->xilinx_rev);
06557         return -1;
06558     }
06559 
06560     if (edt_is_dvcl(pdv_p) || edt_is_dvfox(pdv_p) || (id == PDVA_ID))
06561         donew = 1;
06562 
06563     switch (baud)
06564     {
06565     case 9600:
06566         baudbits = 0;
06567         baudreg = 0x80;
06568         break;
06569 
06570     case 19200:
06571         baudbits = PDV_BAUD0;
06572         baudreg = 0x3f;
06573         break;
06574 
06575     case 38400:
06576         baudbits = PDV_BAUD1;
06577         baudreg = 0x1f;
06578         break;
06579 
06580     case 115200:
06581         baudbits = PDV_BAUD0 | PDV_BAUD1;
06582         baudreg = 0x09;
06583         break;
06584 
06585     case 57600:
06586         baudbits = PDV_BAUD0 | PDV_BAUD1;       /* ALERT (funky old DV or DVK only) */
06587         donew = 1;
06588         baudreg = 0x014;
06589         break;
06590 
06591     default:
06592         donew = 1;
06593         baudreg = (unsigned int)(((20000000.0 / (16.0 * (double)baud)) - 2.0) + 0.5) ; 
06594         edt_msg(DBG2, "pdv_set_baud(%d) using new method, reg %02x\n", baud, baudreg);
06595         break;
06596     }
06597 
06598     if (donew && (!dd_p->register_wrap))
06599     {
06600         if (baudreg > 0xff)
06601         {
06602             edt_msg(DBG2, "pdv_set_baud(%d) (baudreg %x) BAD VALUE not set\n", baud, baudreg);
06603             ret = -1; 
06604         }
06605         else 
06606         {
06607             edt_msg(DBG2, "pdv_set_baud(%d) (baudreg %x) using NEW baud reg\n", baud, baudreg);
06608             edt_reg_write(pdv_p, PDV_BRATE, baudreg);
06609             new = edt_reg_read(pdv_p, PDV_BRATE);
06610             if (new != baudreg)
06611             {
06612                 edt_msg(DBG2, "pdv_set_baud(%d) wrote %x read %x) readback ERROR\n", baud, baudreg, new);
06613                 ret = -1;
06614             }
06615         }
06616     }
06617 
06618     else /* old way */
06619     {
06620         edt_msg(DBG2, "pdv_set_baud(%d) (baudbits %x) using OLD baud bits\n", baud, baudbits);
06621         cntl = edt_reg_read(pdv_p, PDV_SERIAL_DATA_CNTL);
06622         cntl &= ~PDV_BAUD_MASK;
06623         cntl |= baudbits;
06624         edt_reg_write(pdv_p, PDV_SERIAL_DATA_CNTL, cntl);
06625     }
06626 
06627     return ret;
06628 }
06629 
06638 int
06639 pdv_get_baud(PdvDev * pdv_p)
06640 {
06641     if (pdv_p->dd_p->serial_baud == NOT_SET)
06642         return 9600;
06643     return pdv_p->dd_p->serial_baud;
06644 }
06645 
06661 void
06662 pdv_perror(char *err)
06663 {
06664     edt_perror(err);
06665 }
06666 
06667 void
06668 pdv_setdebug(PdvDev * pdv_p, int debug)
06669 {
06670     Pdv_debug = debug;
06671 }
06672 
06673 
06674 
06675 
06676 
06689 void
06690 pdv_reset_serial(PdvDev * pdv_p)
06691 {
06692     edt_reset_serial(pdv_p);
06693 }
06694 
06695 
06716 uchar_t *
06717 pdv_alloc(int size)
06718 {
06719     return edt_alloc(size);
06720 }
06721 
06722 
06729 void
06730 pdv_free(uchar_t * ptr)
06731 {
06732     edt_free(ptr);
06733 }
06734 
06735 
06736 
06737 static u_short zero[] = {
06738     0x0F80,
06739     0x3FE0,
06740     0x38E0,
06741     0x7070,
06742     0x6030,
06743     0xE038,
06744     0xE038,
06745     0xE038,
06746     0xE038,
06747     0xE038,
06748     0xE038,
06749     0xE038,
06750     0x6030,
06751     0x7070,
06752     0x38E0,
06753     0x3FE0,
06754     0x0F80,
06755 };
06756 static u_short one[] = {
06757     0xFC00,
06758     0xFC00,
06759     0x1C00,
06760     0x1C00,
06761     0x1C00,
06762     0x1C00,
06763     0x1C00,
06764     0x1C00,
06765     0x1C00,
06766     0x1C00,
06767     0x1C00,
06768     0x1C00,
06769     0x1C00,
06770     0x1C00,
06771     0x1C00,
06772     0xFF80,
06773     0xFF80,
06774 };
06775 static u_short two[] = {
06776     0x7E00,
06777     0x7F80,
06778     0x4380,
06779     0x01C0,
06780     0x01C0,
06781     0x01C0,
06782     0x01C0,
06783     0x0380,
06784     0x0700,
06785     0x0E00,
06786     0x1C00,
06787     0x3800,
06788     0x3800,
06789     0x7000,
06790     0xE000,
06791     0xFFC0,
06792     0xFFC0,
06793 };
06794 static u_short three[] = {
06795     0x7E00,
06796     0xFF00,
06797     0x8780,
06798     0x0380,
06799     0x0380,
06800     0x0380,
06801     0x0F00,
06802     0x7C00,
06803     0x7E00,
06804     0x0F00,
06805     0x0380,
06806     0x0380,
06807     0x0380,
06808     0x0380,
06809     0x8700,
06810     0xFF00,
06811     0xFC00,
06812 };
06813 static u_short four[] = {
06814     0x0380,
06815     0x0780,
06816     0x0F80,
06817     0x0F80,
06818     0x1F80,
06819     0x1B80,
06820     0x3380,
06821     0x3380,
06822     0x6380,
06823     0xE380,
06824     0xFFE0,
06825     0xFFE0,
06826     0xFFE0,
06827     0x0380,
06828     0x0380,
06829     0x0380,
06830     0x0380,
06831 };
06832 static u_short five[] = {
06833     0xFF80,
06834     0xFF80,
06835     0xE000,
06836     0xE000,
06837     0xE000,
06838     0xC000,
06839     0xF800,
06840     0xFE00,
06841     0x0F00,
06842     0x0780,
06843     0x0380,
06844     0x0380,
06845     0x0380,
06846     0x0380,
06847     0x8700,
06848     0xFE00,
06849     0xFC00,
06850 };
06851 static u_short six[] = {
06852     0x07E0,
06853     0x1FE0,
06854     0x3C20,
06855     0x7000,
06856     0x7000,
06857     0xE000,
06858     0xE780,
06859     0xFFE0,
06860     0xF0E0,
06861     0xE070,
06862     0xE070,
06863     0xE070,
06864     0xE070,
06865     0x7070,
06866     0x70E0,
06867     0x3FC0,
06868     0x0F80,
06869 };
06870 static u_short seven[] = {
06871     0xFFC0,
06872     0xFFC0,
06873     0x01C0,
06874     0x0180,
06875     0x0380,
06876     0x0700,
06877     0x0700,
06878     0x0E00,
06879     0x0C00,
06880     0x1C00,
06881     0x1800,
06882     0x3800,
06883     0x3800,
06884     0x3000,
06885     0x7000,
06886     0x7000,
06887     0x7000,
06888 };
06889 static u_short eight[] = {
06890     0x0F80,
06891     0x3FC0,
06892     0x71E0,
06893     0x70E0,
06894     0x70E0,
06895     0x7DE0,
06896     0x3FC0,
06897     0x1F00,
06898     0x1FC0,
06899     0x7FE0,
06900     0xF1F0,
06901     0xE0F0,
06902     0xE070,
06903     0xE070,
06904     0xF0E0,
06905     0x7FE0,
06906     0x1F80,
06907 };
06908 static u_short nine[] = {
06909     0x1F00,
06910     0x3FC0,
06911     0x70E0,
06912     0xE0E0,
06913     0xE070,
06914     0xE070,
06915     0xE070,
06916     0xE070,
06917     0x70F0,
06918     0x7FF0,
06919     0x1E70,
06920     0x0070,
06921     0x00E0,
06922     0x00E0,
06923     0x43C0,
06924     0x7F80,
06925     0x7E00,
06926 };
06927 
06928 static u_short *digits[] = {
06929     zero,
06930     one,
06931     two,
06932     three,
06933     four,
06934     five,
06935     six,
06936     seven,
06937     eight,
06938     nine,
06939 };
06940 
06941 
06942 static void
06943 set_square_32(int sx, int sy, u_short * buf, u_int * addr, int stride, int fg)
06944 {
06945     /*
06946     * colors
06947     */
06948 
06949 #define BG16    0
06950 
06951     /*
06952     * get offset to square
06953     */
06954     register u_int *svptr;
06955     register u_int *ptr;
06956     int     i;
06957     int     bit;
06958     u_short tmp;
06959     int     val;
06960 
06961     svptr = addr + (stride * sy) + (sx);
06962 
06963     for (i = 0; i < 17; i++)
06964     {
06965         ptr = svptr;
06966         tmp = *buf++;
06967         for (bit = 15; bit >= 0; bit--)
06968         {
06969             if (tmp & (1 << bit))
06970             {
06971                 val = fg;
06972             }
06973             else
06974             {
06975                 val = BG16;
06976             }
06977             *ptr++ = val;
06978         }
06979         svptr += stride;
06980     }
06981 }
06982 
06983 
06984 static void
06985 set_square_16(int sx, int sy, u_short * buf, u_short * addr, int stride, int fg)
06986 {
06987     /*
06988     * colors
06989     */
06990 
06991 #define BG16    0
06992 
06993     /*
06994     * get offset to square
06995     */
06996     register u_short *svptr;
06997     register u_short *ptr;
06998     int     i;
06999     int     bit;
07000     u_short tmp;
07001     int     val;
07002 
07003     svptr = addr + (stride * sy) + (sx);
07004 
07005     for (i = 0; i < 17; i++)
07006     {
07007         ptr = svptr;
07008         tmp = *buf++;
07009         for (bit = 15; bit >= 0; bit--)
07010         {
07011             if (tmp & (1 << bit))
07012             {
07013                 val = fg;
07014             }
07015             else
07016             {
07017                 val = BG16;
07018             }
07019             *ptr++ = val;
07020         }
07021         svptr += stride;
07022     }
07023 }
07024 
07025 static void
07026 set_square(int sx, int sy, u_short * buf, u_char * addr, int stride, int fg)
07027 {
07028     /*
07029     * colors
07030     */
07031 
07032 #define BG      0
07033 
07034     /*
07035     * get offset to square
07036     */
07037     register u_char *svptr;
07038     register u_char *ptr;
07039     int     i;
07040     int     bit;
07041     u_short tmp;
07042     int     val;
07043 
07044     svptr = addr + (stride * sy) + (sx);
07045 
07046     for (i = 0; i < 17; i++)
07047     {
07048         ptr = svptr;
07049         tmp = *buf++;
07050         for (bit = 15; bit >= 0; bit--)
07051         {
07052             if (tmp & (1 << bit))
07053             {
07054                 val = fg;
07055             }
07056             else
07057             {
07058                 val = BG;
07059             }
07060             *ptr++ = val;
07061         }
07062         svptr += stride;
07063     }
07064 }
07065 
07066 void
07067 pdv_mark_digit_16(u_short * addr, int n, int width, int height, int x, int y,
07068                   int mask, int fg)
07069 
07070 {
07071     int dig = n % 10;
07072 
07073     set_square_16(x, y, digits[dig], addr, width, fg);
07074 
07075 }
07076 
07077 void
07078 pdv_mark_digit_32(u_int * addr, int n, int width, int height, int x, int y,
07079                   int mask, int fg)
07080 
07081 {
07082     int dig = n % 10;
07083 
07084     set_square_32(x, y, digits[dig], addr, width, fg);
07085 
07086 }
07087 
07088 void
07089 pdv_mark_digit_24(u_char * addr, int n, int width, int height, int x, int y,
07090                   int mask, int fg)
07091 
07092 {
07093     int dig = n % 10;
07094 
07095     set_square(x, y, digits[dig], addr, width, fg);
07096 
07097 }
07098 
07099 void
07100 pdv_mark_digit_8(u_char * addr, int n, int width, int height, int x, int y,
07101                  int mask, int fg)
07102 
07103 {
07104     int dig = n % 10;
07105 
07106     set_square(x, y, digits[dig], addr, width, fg);
07107 
07108 }
07109 
07110 void
07111 pdv_mark_ras_depth(void * addr, int n, int width, int height, int x, int y, int depth, int fg)
07112 {
07113 #define GAP     16
07114     int div = 1000000;
07115 
07116     int i;
07117 
07118     for (i=0;div>=1;i++)
07119     {
07120 
07121         if (n > div)
07122         {
07123             int val = (n / div) % 10;
07124 
07125             switch(depth)
07126             {
07127             case 8:
07128                 pdv_mark_digit_8((u_char *) addr, val, width, height, x + (GAP * i), y, 1, fg);
07129                 break;
07130             case 16:
07131                 pdv_mark_digit_16((u_short *) addr, val, width, height, x + (GAP * i), y, 1, fg);
07132                 break;
07133             case 24:
07134                 pdv_mark_digit_24((u_char *) addr, val, width, height, x + (GAP * i), y, 1, fg);
07135                 break;
07136             case 32:
07137                 pdv_mark_digit_32((u_int *) addr, val, width, height, x + (GAP * i), y, 1, fg);
07138                 break;
07139             }
07140         }
07141 
07142         div /= 10;
07143     }
07144 }
07145 
07146 void
07147 pdv_mark_bin_16(u_short * addr, int n, int width, int height, int x, int y)
07148 {
07149     u_int   val = n;
07150     u_char *svptr;
07151 
07152     svptr = (u_char *) addr + (width * y) + x;
07153     *svptr++ = (val >> 24) & 0xff;
07154     *svptr++ = (val >> 16) & 0xff;
07155     *svptr++ = (val >> 8) & 0xff;
07156     *svptr++ = val & 0xff;
07157 }
07158 
07159 
07160 void
07161 pdv_mark_ras(u_char * addr, int n, int width, int height, int x, int y)
07162 {
07163 #define GAP     16
07164     int div = 1000000;
07165     int i;
07166 
07167     for (i=0;div;i++)
07168     {
07169         pdv_mark_digit_8(addr, n, width, height, x + (GAP * i), y, div, 200);
07170         div /= 10;
07171     }
07172 }
07173 
07174 void
07175 pdv_mark_bin(u_char * addr, int n, int width, int height, int x, int y)
07176 {
07177     u_int   val = n;
07178     u_char *svptr;
07179 
07180     svptr = (u_char *) addr + (width * y) + x;
07181     *svptr++ = (val >> 24) & 0xff;
07182     *svptr++ = (val >> 16) & 0xff;
07183     *svptr++ = (val >> 8) & 0xff;
07184     *svptr++ = val & 0xff;
07185 }
07186 
07204 int
07205 pdv_serial_command_hex(PdvDev * pdv_p, const char *str, int length)
07206 {
07207     char    buf[2];
07208     const char   *p = &str[2];
07209     u_int   lval;
07210 
07211     sscanf(p, "%x", &lval);
07212     buf[0] = (char) (lval & 0xff);
07213     edt_msg(DBG2, "pdv_serial_command_hex(%s),0x%x\n", str, (u_char) (buf[0]));
07214 
07215     return pdv_serial_binary_command(pdv_p, buf, 1);
07216 }
07217 
07261 int
07262 pdv_set_roi(PdvDev * pdv_p, int hskip, int hactv, int vskip, int vactv)
07263 {
07264     Dependent *dd_p = pdv_p->dd_p;
07265     int     cam_w, cam_h;       /* camera actual w/h */
07266 
07267     edt_msg(DBG2, "pdv_set_roi(hskip %d hactv %d vskip %d vactv %d)\n",
07268         hskip, hactv, vskip, vactv);
07269 
07270     /*
07271     * ALERT: check for ROI xilinx capabilities here -- 4005 doesn't do ROI
07272     */
07273     if (dd_p->xilinx_rev < 2 || dd_p->xilinx_rev > 32)
07274     {
07275         edt_msg(DBG2, "pdv_set_roi(): WARNING: can't enable, N/A this xilinx (%x)\n",
07276             dd_p->xilinx_rev);
07277         return -1;
07278     }
07279 
07280     cam_w = pdv_get_cam_width(pdv_p);
07281     cam_h = pdv_get_cam_height(pdv_p);
07282 
07283     /* check width/height for out of range, unless camera link or FOI */
07284     if (!pdv_is_cameralink(pdv_p))
07285     {
07286         if ((cam_w && ((hskip + hactv) > cam_w)) || ((hskip + hactv) <= 0))
07287         {
07288             edt_msg(DBG2, "ROI: horiz. skip/actv out of range error\n");
07289             return -1;
07290         }
07291         if ((cam_h && ((vskip + vactv) > cam_h)) || ((vskip + vactv) <= 0))
07292         {
07293             edt_msg(DBG2, "ROI: vert. skip/actv out of range error\n");
07294             return -1;
07295         }
07296     }
07297 
07298     /* vert must be even, and regs set to value/taps  */
07299     if (pdv_is_cameralink(pdv_p))
07300     {
07301         if (dd_p->htaps > 0)
07302         {
07303             hactv = (hactv / dd_p->htaps) * dd_p->htaps;
07304             hskip = (hskip / dd_p->htaps) * dd_p->htaps;
07305 
07306             edt_reg_write(pdv_p, PDV_HSKIP, (hskip / dd_p->htaps));
07307             edt_reg_write(pdv_p, PDV_HACTV, (hactv / dd_p->htaps) - 1);
07308         }
07309 
07310         if (dd_p->vtaps > 0)
07311         {
07312             vactv = (vactv / dd_p->vtaps) * dd_p->vtaps;
07313             vskip = (vskip / dd_p->vtaps) * dd_p->vtaps;
07314 
07315             edt_reg_write(pdv_p, PDV_VSKIP, (vskip / dd_p->vtaps));
07316             edt_reg_write(pdv_p, PDV_VACTV, (vactv / dd_p->vtaps) - 1);
07317         }
07318     }
07319     else if (dd_p->dual_channel)
07320     {
07321         vactv = (vactv / 2) * 2;
07322         vskip = (vskip / 2) * 2;
07323         edt_reg_write(pdv_p, PDV_VSKIP, (vskip / 2));
07324         edt_reg_write(pdv_p, PDV_HSKIP, hskip);
07325         edt_reg_write(pdv_p, PDV_VACTV, (vactv / 2) - 1);
07326         edt_reg_write(pdv_p, PDV_HACTV, hactv - 1);
07327     }
07328     else
07329     {
07330         edt_reg_write(pdv_p, PDV_HSKIP, hskip);
07331         edt_reg_write(pdv_p, PDV_VSKIP, vskip);
07332         edt_reg_write(pdv_p, PDV_HACTV, hactv - 1);
07333         edt_reg_write(pdv_p, PDV_VACTV, vactv - 1);
07334     }
07335 
07336     dd_p->hactv = hactv;
07337     dd_p->hskip = hskip;
07338     dd_p->vactv = vactv;
07339     dd_p->vskip = vskip;
07340 
07341     if (dd_p->roi_enabled)
07342         pdv_setsize(pdv_p, dd_p->hactv, dd_p->vactv);
07343 
07344     edt_set_dependent(pdv_p, dd_p);
07345 
07346     return 0;                   /* ALERT: need to return error from above if
07347                                 * any */
07348 }
07349 
07350 
07351 void
07352 pdv_cl_set_base_channels(PdvDev *pdv_p, int htaps, int vtaps)
07353 
07354 {
07355     Dependent *dd_p = pdv_p->dd_p;
07356     int taps = (htaps > vtaps)? htaps : vtaps;
07357 
07358     dd_p->cl_data_path = (taps - 1) << 4 | (dd_p->depth - 1);
07359 
07360     dd_p->htaps = htaps;
07361     dd_p->vtaps = vtaps;
07362 
07363     edt_reg_write(pdv_p, PDV_CL_DATA_PATH, dd_p->cl_data_path);
07364 
07365     edt_set_dependent(pdv_p, dd_p);
07366 
07367     pdv_set_roi(pdv_p, dd_p->hskip, dd_p->hactv, dd_p->vskip, dd_p->vactv);
07368 }
07369 
07370 
07371 
07372 /*****************************************************/
07373 /* Set the Dalsa line scan using AIAG - hskip and hactv */
07374 /* control the exposure time and the linerate */
07375 /*****************************************************/
07376 
07377 int
07378 pdv_dalsa_ls_set_expose(PdvDev * pdv_p, int hskip, int hactv)
07379 {
07380     Dependent *dd_p = pdv_p->dd_p;
07381 
07382     edt_msg(DBG2, "pdv_dalsa_ls_set_expose(hskip %d hactv %d)\n", hskip, hactv);
07383 
07384     /*
07385     * ALERT: check for ROI xilinx capabilities here -- 4005 doesn't do ROI
07386     */
07387     if (dd_p->xilinx_rev < 2 || dd_p->xilinx_rev > 32)
07388     {
07389         edt_msg(DBG2, "pdv_dalsa_ls_set_expose(): WARNING: can't enable, N/A this xilinx (%x)\n", dd_p->xilinx_rev);
07390         return -1;
07391     }
07392 
07393     edt_reg_write(pdv_p, PDV_HSKIP, hskip);
07394     edt_reg_write(pdv_p, PDV_HACTV, hactv - 1);
07395 
07396     dd_p->hactv = hactv;
07397     dd_p->hskip = hskip;
07398 
07399     edt_set_dependent(pdv_p, dd_p);
07400     pdv_enable_roi(pdv_p, 1);
07401 
07402     return 0;                   /* ALERT: need to return error from above if *
07403                                 * any */
07404 }
07405 
07406 
07415 int
07416 pdv_auto_set_roi(PdvDev * pdv_p)
07417 {
07418     int     w = pdv_p->dd_p->width;
07419     int     h = pdv_p->dd_p->height;
07420     int     ret;
07421 
07422     edt_msg(DBG2, "pdv_auto_set_roi()\n");
07423 
07424     if ((ret = pdv_set_roi(pdv_p, 0, w, 0, h)) == 0)
07425     {
07426         if (pdv_is_cameralink(pdv_p))
07427             pdv_setsize(pdv_p, pdv_p->dd_p->hactv, pdv_p->dd_p->vactv);
07428         ret = pdv_enable_roi(pdv_p, 1);
07429     }
07430 
07431     return ret;
07432 }
07433 
07456 int
07457 pdv_enable_roi(PdvDev * pdv_p, int flag)
07458 {
07459     u_int   roictl;
07460     Dependent *dd_p = pdv_p->dd_p;
07461 
07462     /* NEW 6/20 -- CL NOT always enabled; modified accordingly */
07463     if (pdv_is_cameralink(pdv_p))
07464     {
07465         if (flag) /* enable */
07466         {
07467             edt_reg_and(pdv_p, PDV_CL_CFG, ~0x08); /* !! bit should have a label */
07468             pdv_setsize(pdv_p, dd_p->hactv, dd_p->vactv);
07469         }
07470         else /* disable */
07471         {
07472             edt_reg_or(pdv_p, PDV_CL_CFG, 0x08);
07473             pdv_setsize(pdv_p, dd_p->cam_width, dd_p->cam_height);
07474         }
07475 
07476         dd_p->roi_enabled = flag;
07477 
07478         return 0;
07479     }
07480 
07481     if (dd_p->xilinx_rev < 2 || dd_p->xilinx_rev > 32)
07482     {
07483         edt_msg(DBG2, "pdv_enable_roi(): can't enable, N/A this xilinx (%x)\n", dd_p->xilinx_rev);
07484         return -1;
07485     }
07486 
07487     edt_msg(DBG2, "pdv_enable_roi(%d): %sabling\n", flag, flag ? "EN" : "DIS");
07488 
07489     /* edt_msleep(100); */
07490 
07491     roictl = edt_reg_read(pdv_p, PDV_ROICTL);
07492 
07493 
07494     if (flag)                   /* enable ROI */
07495     {
07496         roictl |= PDV_ROICTL_ROI_EN;
07497         edt_reg_write(pdv_p, PDV_ROICTL, roictl);
07498         pdv_setsize(pdv_p, dd_p->hactv, dd_p->vactv);
07499     }
07500     else                        /* disable ROI */
07501     {
07502         /* ALERT -- not a R/W reg so can't and/or bits */
07503         roictl &= ~PDV_ROICTL_ROI_EN;
07504         edt_reg_write(pdv_p, PDV_ROICTL, roictl);
07505         pdv_setsize(pdv_p, dd_p->cam_width, dd_p->cam_height);
07506     }
07507 
07508     dd_p->roi_enabled = flag;
07509 
07510     return 0;
07511 }
07512 
07532 int
07533 pdv_access(char *fname, int perm)
07534 {
07535     return edt_access(fname, perm);
07536 }
07537 
07538 
07562 int
07563 pdv_strobe(PdvDev * pdv_p, int count, int delay)
07564 {
07565     if (pdv_strobe_method(pdv_p) != PDV_LHS_METHOD1)
07566         return -1;
07567 
07568     edt_msg(DBG2, "pdv_strobe(%d %d)\n", count, delay);
07569 
07570     edt_reg_write(pdv_p, PDV_SHUTTER, delay);
07571 
07572     /*
07573     * write to LSB loads the low byte, write to MSB loads high byte and also
07574     * fires the strobe
07575     */
07576     edt_reg_write(pdv_p, PDV_FIXEDLEN, count);
07577 
07578     return 0;
07579 }
07580 
07601 int
07602 pdv_set_strobe_counters(PdvDev * pdv_p, int count, int delay, int period)
07603 {
07604     if (pdv_strobe_method(pdv_p) != PDV_LHS_METHOD2)
07605         return -1;
07606 
07607     if (count > 0xfff)
07608     {
07609         edt_msg(DBG1, "pdv_set_strobe_counters() ERROR -- count out of range\n");
07610         return -1;
07611     }
07612 
07613     if (delay > 0xff)
07614     {
07615         edt_msg(PDVWARN, "pdv_set_strobe_counters() ERROR -- delay out of range\n");
07616         return -1;
07617     }
07618 
07619     if (period > 0xff)
07620     {
07621         edt_msg(PDVWARN, "pdv_set_strobe_counters() ERROR -- period out of range\n");
07622         return -1;
07623     }
07624 
07625     edt_msg(DBG2, "pdv_set_strobe_counters(%d %d %d)\n", count, delay, period);
07626 
07627     edt_reg_write(pdv_p, PDV_LHS_DELAY, delay);
07628 
07629     edt_reg_write(pdv_p, PDV_LHS_PERIOD, period);
07630 
07631     /*
07632     * write to the count (2 bytes, combined)
07633     */
07634     edt_reg_write(pdv_p, PDV_LHS_COUNT, count);
07635 
07636     return 0;
07637 }
07638 
07650 int
07651 pdv_enable_strobe(PdvDev * pdv_p, int ena)
07652 {
07653     int method = pdv_strobe_method(pdv_p);
07654 
07655     if (pdv_p->devid == PDVFOI_ID)
07656         return -1;
07657 
07658     if (method == 0)
07659         return -1;
07660 
07661     if (method == PDV_LHS_METHOD1)
07662     {
07663         if (ena == 0)
07664             return -1;
07665         return 0;
07666     }
07667 
07668     if (ena)
07669         edt_reg_write(pdv_p, PDV_LHS_CONTROL, PDV_LHS_ENABLE);
07670     else edt_reg_write(pdv_p, PDV_LHS_CONTROL, 0);
07671 
07672     return 0;
07673 }
07674 
07685 int
07686 pdv_strobe_method(PdvDev *pdv_p)
07687 {
07688     Dependent *dd_p = pdv_p->dd_p;
07689 
07690     if (dd_p->strobe_enabled == NOT_SET)
07691     {
07692         int reg ;
07693 
07694         /* default to not enabled */
07695         dd_p->strobe_enabled = 0;
07696 
07697         if (pdv_p->devid == PDVFOI_ID)
07698             return 0;
07699 
07700         /* ALERT: figure out somehow whether LH strobe flash is loaded
07701         * but for now just return lhs2 */
07702         if (pdv_p->devid == PDVCL_ID)
07703         {
07704             dd_p->strobe_enabled = PDV_LHS_METHOD2;
07705             return dd_p->strobe_enabled;
07706         }
07707 
07708         /* old xilinx revs didn't have strobe, so just bail out here */
07709         if (dd_p->xilinx_rev < 2 || dd_p->xilinx_rev > 32)
07710             return 0;
07711 
07712         /*
07713         * see if new LHS registers are there (can be written/read)
07714         */
07715         if (!dd_p->register_wrap)
07716         {
07717             reg = edt_reg_read(pdv_p, PDV_LHS_COUNT_HI);
07718             edt_reg_write(pdv_p, PDV_LHS_COUNT_HI, 0x50);
07719             if (edt_reg_read(pdv_p, PDV_LHS_COUNT_HI) == 0x50)
07720             {
07721                 edt_reg_write(pdv_p, PDV_LHS_COUNT_HI, reg);
07722                 dd_p->strobe_enabled = PDV_LHS_METHOD2;
07723                 return dd_p->strobe_enabled;
07724             }
07725         }
07726 
07727         /* still here? okay check for (infer) OLD strobe method */
07728         if (pdv_p->devid != PDVFOI_ID)
07729         {
07730             int     status = edt_reg_read(pdv_p, PDV_SERIAL_DATA_STAT);
07731 
07732             if (status & LHS_DONE)
07733                 dd_p->strobe_enabled = PDV_LHS_METHOD1;
07734         }
07735     }
07736 
07737     return dd_p->strobe_enabled;
07738 }
07739 
07740 
07760 int
07761 pdv_set_strobe_dac(PdvDev * pdv_p, u_int value)
07762 {
07763     int     i;
07764     int     reg;
07765     int     method;
07766     u_int   mcl, mask;
07767     u_char  data;
07768 
07769     if ((method = pdv_strobe_method(pdv_p)) == 0)
07770         return -1;
07771 
07772     if (method == PDV_LHS_METHOD2)
07773         reg = PDV_LHS_CONTROL;
07774     else reg = PDV_MODE_CNTL;
07775 
07776     edt_msg(DBG2, "pdv_strobe(%d)\n", value);
07777 
07778     mcl = edt_reg_read(pdv_p, reg) & 0x0f;      /* preserve low bits */
07779 
07780     /*
07781     * dac is high nibble of register with strobe xilinx first we clear, then
07782     * set low bit
07783     */
07784     edt_reg_write(pdv_p, reg, mcl | PDV_LHS_DAC_LOAD);
07785 
07786     /*
07787     * shift in 16 bits
07788     */
07789     for (i = 0; i < 16; i++)
07790     {
07791         mask = (value & (1 << (15 - i)));
07792 
07793         if (mask)
07794             data = PDV_LHS_DAC_DATA;
07795         else
07796             data = 0;
07797 
07798         edt_reg_write(pdv_p, reg, mcl | PDV_LHS_DAC_LOAD | data);
07799         edt_reg_write(pdv_p, reg, mcl | PDV_LHS_DAC_LOAD | PDV_LHS_DAC_CLOCK | data);
07800         edt_reg_write(pdv_p, reg, mcl | PDV_LHS_DAC_LOAD | data);
07801         edt_reg_write(pdv_p, reg, mcl | PDV_LHS_DAC_LOAD);
07802     }
07803 
07804     edt_reg_write(pdv_p, reg, mcl &~ PDV_LHS_DAC_LOAD);
07805     return 0;
07806 }
07807 
07815 void
07816 pdv_flush_channel_fifo(PdvDev * pdv_p)
07817 {
07818 
07819     /* now obsolete channel reset is fixed for FOX 
07820     jsc 3/6/06 */
07821 
07822     pdv_flush_fifo(pdv_p);
07823 }
07824 
07843 void
07844 pdv_flush_fifo(PdvDev * pdv_p)
07845 {
07846     /* previously in comment: @see edt_set_firstflush */
07847     if (pdv_p->devid == PDV_ID ||
07848         pdv_p->devid == PDVK_ID ||
07849         pdv_p->devid == PDVFOI_ID ||
07850         pdv_p->devid == PDVA_ID)
07851     {
07852         edt_flush_fifo(pdv_p);
07853         return;
07854     }
07855 
07856     if (pdv_p->devid == PDVCL_ID || 
07857         pdv_p->devid == PE8DVCL_ID ||
07858         pdv_p->devid == PE8DVCLS_ID ||
07859         pdv_p->devid == PE4DVCL_ID)
07860     {
07861         /* RFIFO doesnt exist on camera link */
07862         /* doing the reset intfc here may cause problems */
07863         /* possibly when it happens in same frame as grab - TODO - check */
07864         u_int cfg ;
07865           
07866         cfg = edt_intfc_read(pdv_p, PDV_CFG);
07867         cfg &= ~PDV_FIFO_RESET;
07868         edt_intfc_write(pdv_p, PDV_CMD, PDV_RESET_INTFC);
07869         edt_intfc_write(pdv_p, PDV_CFG, (u_char) (cfg | PDV_FIFO_RESET));
07870         edt_intfc_write(pdv_p, PDV_CFG, cfg);
07871         edt_flush_channel(pdv_p, pdv_p->channel_no);
07872 
07873     }
07874     else if  (pdv_p->devid == PDVFOI_ID)
07875     {
07876         char tmpbuf[10];
07877         int ret;
07878 
07879         ret = pdv_serial_wait(pdv_p, 100, 0);
07880         if (ret > 10)
07881             pdv_reset_serial(pdv_p);
07882         else
07883             pdv_serial_read(pdv_p, tmpbuf, ret);
07884     }
07885     else
07886     {
07887         /* DV-FOX, PCIe C-Link */
07888 
07889         u_int cfg ;
07890         cfg = edt_intfc_read(pdv_p, PDV_CFG);
07891         cfg &= ~PDV_FIFO_RESET;
07892         edt_intfc_write(pdv_p, PDV_CFG, (u_char) (cfg | PDV_FIFO_RESET));
07893         edt_flush_channel(pdv_p, pdv_p->channel_no);
07894         edt_intfc_write(pdv_p, PDV_CFG, cfg);
07895     }
07896 }
07897 
07901 void
07902 pdv_setup_continuous_channel(PdvDev * pdv_p)
07903 
07904 {
07905     /* now obsolete channel reset is fixed for FOX 
07906     jsc 3/6/06 */
07907     pdv_setup_continuous(pdv_p);
07908 }
07909 
07918 void
07919 pdv_setup_continuous(PdvDev * pdv_p)
07920 {
07921     pdv_flush_fifo(pdv_p);
07922 
07923     if (pdv_p->devid == PDV_ID ||
07924         pdv_p->devid == PDVK_ID ||
07925         pdv_p->devid == PDVA_ID)
07926     {
07927 
07928         if (edt_get_firstflush(pdv_p) != EDT_ACT_KBS)
07929             edt_set_firstflush(pdv_p, EDT_ACT_ONCE);
07930     }
07931     else
07932     {
07933         edt_set_firstflush(pdv_p,EDT_ACT_NEVER) ;
07934         edt_set_autodir(pdv_p, 0) ;
07935 
07936     }
07937 
07938     edt_startdma_reg(pdv_p, PDV_CMD, PDV_ENABLE_GRAB);
07939 
07940     if (pdv_in_continuous(pdv_p))
07941     {
07942         /* pdv_start_hardware_continuous(pdv_p) ; */
07943         edt_set_continuous(pdv_p, 1);
07944     }
07945     else if (pdv_p->dd_p->fv_once)
07946     {
07947         pdv_start_hardware_continuous(pdv_p);
07948     }
07949     else
07950         edt_set_continuous(pdv_p, 0);
07951 
07952     pdv_p->dd_p->started_continuous = 1;
07953 
07954 }
07955 
07963 void
07964 pdv_stop_continuous(PdvDev * pdv_p)
07965 {
07966 
07967     if (pdv_in_continuous(pdv_p))
07968     {
07969         edt_set_continuous(pdv_p, 0);
07970     }
07971     else if (pdv_p->dd_p->fv_once)
07972         pdv_stop_hardware_continuous(pdv_p); 
07973 
07974     pdv_p->dd_p->started_continuous = 0;
07975 
07976     if (pdv_p->devid == PDVFOI_ID)
07977     {
07978         char    tmpbuf[10];
07979         int     ret;
07980 
07981         ret = pdv_serial_wait(pdv_p, 100, 0);
07982         if (ret > 10)
07983             pdv_reset_serial(pdv_p);
07984         else
07985             pdv_serial_read(pdv_p, tmpbuf, ret);
07986     }
07987 }
07988 
08009 int
08010 pdv_timeout_restart(PdvDev * pdv_p, int restart)
08011 {
08012     int     curdone, curtodo;
08013 
08014     curdone = edt_done_count(pdv_p);
08015     curtodo = edt_get_todo(pdv_p);
08016 
08017     edt_abort_dma(pdv_p);
08018     pdv_stop_continuous(pdv_p);
08019 
08020     edt_set_buffer(pdv_p, curdone);
08021     edt_reg_write(pdv_p, PDV_CMD, PDV_RESET_INTFC);
08022     pdv_setup_continuous(pdv_p);
08023 
08024     if (restart && 
08025         (curtodo - curdone))
08026         pdv_start_images(pdv_p, curtodo - curdone);
08027 
08028     return curtodo - curdone;
08029 }
08030  /* end acquisition */
08032 
08033 /* for debug printfs only */
08034 static char hs[128];
08035 static char *
08036 hex_to_str(char *resp, int n)
08037 {
08038 
08039     int     i;
08040     char   *p = hs;
08041 
08042     for (i = 0; i < n; i++)
08043     {
08044         sprintf(p, "%02x ", resp[i]);
08045         p += 3;
08046     }
08047     *p = '\0';
08048     return hs;
08049 }
08050 
08051 
08062 int
08063 pdv_get_min_shutter(PdvDev * pdv_p)
08064 
08065 {
08066     return pdv_p->dd_p->shutter_speed_min;
08067 }
08068 
08069 
08078 int
08079 pdv_get_max_shutter(PdvDev * pdv_p)
08080 
08081 {
08082     return pdv_p->dd_p->shutter_speed_max;
08083 }
08084 
08085 
08095 int
08096 pdv_get_min_gain(PdvDev * pdv_p)
08097 
08098 {
08099     return pdv_p->dd_p->gain_min;
08100 }
08101 
08102 
08112 int
08113 pdv_get_max_gain(PdvDev * pdv_p)
08114 
08115 {
08116     return pdv_p->dd_p->gain_max;
08117 }
08118 
08119 
08129 int
08130 pdv_get_min_offset(PdvDev * pdv_p)
08131 
08132 {
08133     return pdv_p->dd_p->offset_min;
08134 }
08135 
08136 
08146 int
08147 pdv_get_max_offset(PdvDev * pdv_p)
08148 
08149 {
08150     return pdv_p->dd_p->offset_max;
08151 }
08152 
08159 int
08160 pdv_enable_lock(PdvDev * pdv_p, int flag)
08161 {
08162     Dependent *dd_p = pdv_p->dd_p;
08163     int     ret;
08164 
08165     switch (dd_p->lock_shutter)
08166     {
08167     case KODAK_AIA_MCL:
08168         {
08169             int     mcl = edt_reg_read(pdv_p, PDV_MODE_CNTL);
08170 
08171             if (flag)
08172                 mcl |= PDV_AIA_MC3;
08173             else
08174                 mcl &= ~PDV_AIA_MC3;
08175 
08176             edt_reg_write(pdv_p, PDV_MODE_CNTL, mcl);
08177             ret = 0;
08178             break;
08179         }
08180     case KODAK_AIA_SER:
08181         {
08182             if (flag)
08183                 ret = pdv_serial_command(pdv_p, "SHE OF");
08184             else
08185                 ret = pdv_serial_command(pdv_p, "SHE ON");
08186 
08187             break;
08188         }
08189     case KODAK_SER_14I:
08190         {
08191             if (flag)
08192                 ret = pdv_serial_command(pdv_p, "SHE FO");
08193             else
08194                 ret = pdv_serial_command(pdv_p, "SHE ON");
08195             break;
08196         }
08197     case HAM_4880:
08198         {
08199             if (flag)
08200                 ret = pdv_serial_command(pdv_p, "ASH O");
08201             else
08202                 ret = pdv_serial_command(pdv_p, "ASH A");
08203             break;
08204         }
08205     }
08206     return (ret);
08207 }
08208 
08209 
08214 void
08215 pdv_send_break(PdvDev * pdv_p)
08216 {
08217     u_int   reg;
08218 
08219     edt_msg(DBG2, "pdv_send_break()");
08220 
08221     reg = edt_reg_read(pdv_p, PDV_UTIL2);
08222     edt_reg_write(pdv_p, PDV_UTIL2, reg & ~PDV_MC4);
08223     edt_reg_write(pdv_p, PDV_UTIL2, (reg | PDV_SEL_MC4) & ~PDV_MC4);
08224     edt_msleep(500);
08225     edt_reg_write(pdv_p, PDV_UTIL2, reg & ~PDV_SEL_MC4 & ~PDV_MC4);
08226     edt_reg_write(pdv_p, PDV_UTIL2, reg);
08227 }
08228 
08229 static void
08230 pdv_trigger_specinst(PdvDev * pdv_p)
08231 {
08232     char    cmd = pdv_p->dd_p->serial_trigger[0];
08233 
08234     edt_msg(DBG2, "pdv_trigger_specinst('%c')\n", cmd);
08235 
08236     pdv_serial_binary_command(pdv_p, &cmd, 1);
08237 
08238 }
08239 
08243 static void
08244 pdv_posttrigger_specinst(PdvDev * pdv_p)
08245 {
08246     char    cmd = pdv_p->dd_p->serial_trigger[0];
08247     char    resp[32];
08248     int     ret;
08249     int     waitcnt = 2;
08250 
08251     resp[0] = resp[1] = resp[2] = 0;
08252 
08253 #ifdef SPECINST_WAS
08254     if (pdv_p->devid == PDVFOI_ID)
08255         waitcnt += 2;
08256     if ((ret = pdv_serial_wait(pdv_p, 1500, waitcnt)) == waitcnt)
08257         pdv_serial_read(pdv_p, resp, ret);
08258 #else
08259     if (pdv_p->devid == PDVFOI_ID)
08260         pdv_serial_wait_next(pdv_p, 2000, 0);
08261     else
08262         pdv_serial_wait_next(pdv_p, 2000, 1);
08263     ret = pdv_serial_read(pdv_p, resp, 2);
08264 #endif
08265 
08266     if ((ret != waitcnt)
08267         || (resp[0] != pdv_p->dd_p->serial_trigger[0])
08268         || (resp[1] != pdv_p->dd_p->serial_response[0]))
08269     {
08270         edt_msg(DBG2, "\npdv_posttrigger_specinst: invalid/missing serial?\n");
08271         edt_msg(DBG2, "response (sent %c, ret %d s/b %d, resp <%s>)\n", cmd, ret, waitcnt, (ret > 0) ? resp : "");
08272         return;
08273     }
08274 }
08275 
08276 static int
08277 pdv_specinst_serial_triggered(PdvDev * pdv_p)
08278 {
08279     if (((pdv_p->dd_p->camera_shutter_timing == SPECINST_SERIAL)
08280         || (pdv_p->dd_p->camera_shutter_speed == SPECINST_SERIAL))
08281         && (pdv_p->dd_p->serial_trigger[0]))
08282         return 1;
08283     return 0;
08284 }
08285 
08286 int
08287 pdv_pause_for_serial(PdvDev * pdv_p)
08288 {
08289     return pdv_p->dd_p->pause_for_serial;
08290 }
08291 
08292 
08293 static int
08294 isafloat(char *str)
08295 {
08296     unsigned int i;
08297     int     numdots = 0;
08298     int     numchars = 0;
08299 
08300     for (i = 0; i < strlen(str); i++)
08301     {
08302         if (str[i] == '.')
08303             ++numdots;
08304         else if (isdigit(str[i]))
08305             ++numchars;
08306         else
08307             return 0;
08308     }
08309 
08310     if (numdots == 1 && numchars > 0)
08311         return 1;
08312     return 0;
08313 }
08314 
08315 static int
08316 isdigits(char *str)
08317 {
08318     unsigned int i;
08319     int     numchars = 0;
08320 
08321     for (i = 0; i < strlen(str); i++)
08322     {
08323         if (isdigit(str[i]))
08324             ++numchars;
08325         else if ((str[i] == '-') && (i == 0))
08326             ;
08327         else
08328             return 0;
08329     }
08330 
08331     if (numchars > 0)
08332         return 1;
08333     return 0;
08334 }
08335 
08336 static int
08337 isxdigits(char *str)
08338 {
08339     unsigned int i;
08340     int     numchars = 0;
08341 
08342     for (i = 0; i < strlen(str); i++)
08343     {
08344         if (isxdigit(str[i]))
08345             ++numchars;
08346         else
08347             return 0;
08348     }
08349 
08350     if (numchars > 0)
08351         return 1;
08352     return 0;
08353 }
08354 
08362 int
08363 pdv_is_kodak_i(PdvDev * pdv_p)
08364 {
08365     Dependent *dd_p = pdv_p->dd_p;
08366 
08367     if ((strcmp(dd_p->serial_exposure, "EXE") == 0)
08368         || (strcmp(dd_p->serial_gain, "DGN") == 0)
08369         || (strcmp(dd_p->serial_offset, "GAE") == 0)
08370         || (strcmp(dd_p->serial_offset, "BKE") == 0))
08371         return 1;
08372     return 0;
08373 }
08374 
08375 
08386 int
08387 pdv_is_atmel(PdvDev * pdv_p)
08388 {
08389     Dependent *dd_p = pdv_p->dd_p;
08390 
08391     if ((strncasecmp(dd_p->camera_class, "Atmel", 5) == 0)
08392         || (strncmp(dd_p->serial_exposure, "I=", 2) == 0))
08393         return 1;
08394     return 0;
08395 }
08396 
08404 int
08405 pdv_is_hamamatsu(PdvDev * pdv_p)
08406 {
08407     Dependent *dd_p = pdv_p->dd_p;
08408 
08409     if ((strncasecmp(dd_p->camera_class, "Hamamatsu", 9) == 0)
08410         || (strncmp(dd_p->serial_exposure, "SHT", 3) == 0)
08411         || (strncmp(dd_p->serial_exposure, "FBL", 3) == 0)
08412         || (strncmp(dd_p->serial_exposure, "AET", 3) == 0))
08413         return 1;
08414     return 0;
08415 }
08416 
08417 
08418 
08419 int
08420 pdv_update_values_from_camera(PdvDev * pdv_p)
08421 {
08422     int     ret = 0;
08423 
08424     if (pdv_is_kodak_i(pdv_p))
08425         ret = pdv_update_from_kodak_i(pdv_p);
08426     else if (pdv_is_dvc(pdv_p))
08427         ret = pdv_update_from_dvc(pdv_p);
08428     else if (pdv_is_atmel(pdv_p))
08429         ret = pdv_update_from_atmel(pdv_p);
08430     else if (pdv_is_hamamatsu(pdv_p))
08431         ret = pdv_update_from_hamamatsu(pdv_p);
08432     /* add more here */
08433     else
08434         ret = -1;
08435 
08436     return ret;
08437 }
08438 
08439 static int
08440 pdv_update_from_kodak_i(PdvDev * pdv_p)
08441 {
08442     int     i, n, ret = 0;
08443     char   *stat[64];
08444     char  **stat_p = stat;
08445     Dependent *dd_p = pdv_p->dd_p;
08446 
08447     for (i = 0; i < 64; i++)
08448     {
08449         *stat_p = (char *) malloc(64 * sizeof(char));
08450         **stat_p = '\0';
08451         ++stat_p;
08452     }
08453 
08454     if ((n = pdv_query_serial(pdv_p, "STS?", stat)) < 1)
08455         ret = -1;
08456     else
08457     {
08458         update_int_from_serial(stat, n, "BKE", &dd_p->level);
08459         update_int_from_serial(stat, n, "GAE", &dd_p->gain);
08460         update_int_from_serial(stat, n, "DGN", &dd_p->gain);
08461         update_int_from_serial(stat, n, "EXE", &dd_p->shutter_speed);
08462         update_int_from_serial(stat, n, "BNS", &dd_p->binx);
08463         update_int_from_serial(stat, n, "BNS", &dd_p->biny);
08464     }
08465 
08466     for (i = 0; i < 64; i++)
08467         free(stat[i]);
08468 
08469     return ret;
08470 }
08471 
08472 static int
08473 pdv_update_from_hamamatsu(PdvDev * pdv_p)
08474 {
08475     int     i, n, ret = 0;
08476     char   *stat[64];
08477     char  **stat_p = stat;
08478     Dependent *dd_p = pdv_p->dd_p;
08479 
08480     for (i = 0; i < 64; i++)
08481     {
08482         *stat_p = (char *) malloc(64 * sizeof(char));
08483         **stat_p = '\0';
08484         ++stat_p;
08485     }
08486 
08487     if ((n = pdv_query_serial(pdv_p, "?CEG", stat)) < 1)
08488         ret = -1;
08489     else
08490         update_int_from_serial(stat, n, "CEG", &dd_p->gain);
08491 
08492     if ((n = pdv_query_serial(pdv_p, "?CEO", stat)) < 1)
08493         ret = -1;
08494     else
08495         update_int_from_serial(stat, n, "CEO", &dd_p->level);
08496 
08497     if ((n = pdv_query_serial(pdv_p, "?SHT", stat)) < 1)
08498         ret = -1;
08499     else
08500         update_int_from_serial(stat, n, "SHT", &dd_p->shutter_speed);
08501 
08502     for (i = 0; i < 64; i++)
08503         free(stat[i]);
08504 
08505     return ret;
08506 }
08507 
08508 
08509 static int
08510 pdv_update_from_atmel(PdvDev * pdv_p)
08511 {
08512     int     i, n, ret = 0;
08513     int     tmpval;
08514     char   *stat[64];
08515     char  **stat_p = stat;
08516     Dependent *dd_p = pdv_p->dd_p;
08517 
08518     for (i = 0; i < 64; i++)
08519     {
08520         *stat_p = (char *) malloc(64 * sizeof(char));
08521         **stat_p = '\0';
08522         ++stat_p;
08523     }
08524 
08525     if ((n = pdv_query_serial(pdv_p, "!=3", stat)) < 1)
08526         ret = -1;
08527     else
08528     {
08529         update_int_from_serial(stat, n, "G", &dd_p->gain);
08530         update_int_from_serial(stat, n, "I", &dd_p->shutter_speed);
08531         if (update_int_from_serial(stat, n, "B", &tmpval) == 0)
08532             dd_p->binx = dd_p->biny = tmpval + 1;
08533     }
08534 
08535     for (i = 0; i < 64; i++)
08536         free(stat[i]);
08537 
08538     return ret;
08539 }
08540 
08547 int
08548 pdv_query_serial(PdvDev * pdv_p, char *cmd, char **resp)
08549 {
08550 
08551     char   *buf_p;
08552     char    buf[2048];
08553     int     length;
08554     int     ret;
08555     int     i, j, l;
08556     int     nfound = 0;
08557 
08558     {
08559         char    *tmp_storage;
08560         if ((tmp_storage = (char *)malloc(strlen(cmd)+1)) == NULL)
08561                 return 0;
08562         sprintf(tmp_storage, "%s\r", cmd);
08563         edt_msg(DBG2, "pdv_query_serial: writing <%s>\n", cmd);
08564         pdv_serial_command(pdv_p, tmp_storage);
08565         free(tmp_storage);
08566     }
08567     /*
08568     * serial_timeout comes from the config file (or -t override flag in this
08569     * app), or if not present defaults to 500
08570     */
08571     pdv_serial_wait(pdv_p, pdv_p->dd_p->serial_timeout, 64);
08572 
08573     /*
08574     * get the return string. How its printed out depends on whether its 1)
08575     * ASCII, 2) HEX, or 3) Pulnix STX/ETX format
08576     */
08577     buf_p = buf;
08578     length = 0;
08579     do
08580     {
08581         ret = pdv_serial_read(pdv_p, buf_p, 2048 - length);
08582         edt_msg(DBG2, "read returned %d\n", ret);
08583 
08584         if (ret != 0)
08585         {
08586             buf_p[ret + 1] = 0;
08587             buf_p += ret;
08588             length += ret;
08589         }
08590         if (pdv_p->devid == PDVFOI_ID)
08591             pdv_serial_wait(pdv_p, 500, 0);
08592         else
08593