3 Copyright (c) 2002 Finger Lakes Instrumentation (FLI), L.L.C.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
10 Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
13 Redistributions in binary form must reproduce the above
14 copyright notice, this list of conditions and the following
15 disclaimer in the documentation and/or other materials
16 provided with the distribution.
18 Neither the name of Finger Lakes Instrumentation (FLI), LLC
19 nor the names of its contributors may be used to endorse or
20 promote products derived from this software without specific
21 prior written permission.
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 POSSIBILITY OF SUCH DAMAGE.
36 ======================================================================
38 Finger Lakes Instrumentation, L.L.C. (FLI)
39 web: http://www.fli-cam.com
40 email: support@fli-cam.com
47 #include <sys/param.h>
48 #include <netinet/in.h>
55 #include "libfli-libfli.h"
56 #include "libfli-mem.h"
57 #include "libfli-debug.h"
58 #include "libfli-camera.h"
59 #include "libfli-camera-parport.h"
61 long fli_camera_parport_open(flidev_t dev
)
68 cam
= DEVICE
->device_data
;
70 /* Set timeout values */
77 buf
= htons(C_ADDRESS(1, EPARAM_ECHO
));
78 IO(dev
, &buf
, &wlen
, &rlen
);
79 if (buf
!= htons(C_ADDRESS(1, EPARAM_ECHO
)))
81 debug(FLIDEBUG_FAIL
, "Echo back from camera failed.");
86 buf
= htons(C_ADDRESS(1, EPARAM_DEVICE
));
87 IO(dev
, &buf
, &wlen
, &rlen
);
88 DEVICE
->devinfo
.hwrev
= ntohs(buf
) & 0x00ff;
91 buf
= htons(C_ADDRESS(1, EPARAM_CCDID
));
92 IO(dev
, &buf
, &wlen
, &rlen
);
93 DEVICE
->devinfo
.devid
= ntohs(buf
) & 0x00ff;
95 for (id
= 0; knowndev
[id
].index
!= 0; id
++)
96 if (knowndev
[id
].index
== DEVICE
->devinfo
.devid
)
99 if (knowndev
[id
].index
== 0)
102 cam
->ccd
.array_area
.ul
.x
= knowndev
[id
].array_area
.ul
.x
;
103 cam
->ccd
.array_area
.ul
.y
= knowndev
[id
].array_area
.ul
.y
;
104 cam
->ccd
.array_area
.lr
.x
= knowndev
[id
].array_area
.lr
.x
;
105 cam
->ccd
.array_area
.lr
.y
= knowndev
[id
].array_area
.lr
.y
;
106 cam
->ccd
.visible_area
.ul
.x
= knowndev
[id
].visible_area
.ul
.x
;
107 cam
->ccd
.visible_area
.ul
.y
= knowndev
[id
].visible_area
.ul
.y
;
108 cam
->ccd
.visible_area
.lr
.x
= knowndev
[id
].visible_area
.lr
.x
;
109 cam
->ccd
.visible_area
.lr
.y
= knowndev
[id
].visible_area
.lr
.y
;
110 cam
->ccd
.pixelwidth
= knowndev
[id
].pixelwidth
;
111 cam
->ccd
.pixelheight
= knowndev
[id
].pixelheight
;
113 if ((DEVICE
->devinfo
.model
=
114 (char *)xmalloc(strlen(knowndev
[id
].model
) + 1)) == NULL
)
116 strcpy(DEVICE
->devinfo
.model
, knowndev
[id
].model
);
118 debug(FLIDEBUG_INFO
, " Name: %s", DEVICE
->devinfo
.devnam
);
119 debug(FLIDEBUG_INFO
, " Array: (%4d,%4d),(%4d,%4d)",
120 cam
->ccd
.array_area
.ul
.x
,
121 cam
->ccd
.array_area
.ul
.y
,
122 cam
->ccd
.array_area
.lr
.x
,
123 cam
->ccd
.array_area
.lr
.y
);
124 debug(FLIDEBUG_INFO
, " Visible: (%4d,%4d),(%4d,%4d)",
125 cam
->ccd
.visible_area
.ul
.x
,
126 cam
->ccd
.visible_area
.ul
.y
,
127 cam
->ccd
.visible_area
.lr
.x
,
128 cam
->ccd
.visible_area
.lr
.y
);
131 buf
= htons(C_ADDRESS(1, EPARAM_SNHIGH
));
132 IO(dev
, &buf
, &wlen
, &rlen
);
133 DEVICE
->devinfo
.serno
= (ntohs(buf
) & 0x00ff) << 8;
136 buf
= htons(C_ADDRESS(1, EPARAM_SNLOW
));
137 IO(dev
, &buf
, &wlen
, &rlen
);
138 DEVICE
->devinfo
.serno
|= (ntohs(buf
) & 0x00ff);
141 buf
= htons(C_ADDRESS(1, EPARAM_FIRM
));
142 IO(dev
, &buf
, &wlen
, &rlen
);
143 DEVICE
->devinfo
.fwrev
= (ntohs(buf
) & 0x00ff);
145 /* Initialize all varaibles to something */
146 switch(DEVICE
->devinfo
.hwrev
)
149 cam
->tempslope
= (100.0 / 201.1);
150 cam
->tempintercept
= (-61.613);
154 cam
->tempslope
= (70.0 / 215.75);
155 cam
->tempintercept
= (-52.5681);
159 debug(FLIDEBUG_WARN
, "Could not set temperature parameters.");
167 cam
->image_area
.ul
.x
= cam
->ccd
.visible_area
.ul
.x
;
168 cam
->image_area
.ul
.y
= cam
->ccd
.visible_area
.ul
.y
;
169 cam
->image_area
.lr
.x
= cam
->ccd
.visible_area
.lr
.x
;
170 cam
->image_area
.lr
.y
= cam
->ccd
.visible_area
.lr
.y
;
172 cam
->frametype
= FLI_FRAME_TYPE_NORMAL
;
174 cam
->bitdepth
= FLI_MODE_16BIT
;
178 (cam
->image_area
.lr
.x
- cam
->image_area
.ul
.x
) / cam
->hbin
;
179 cam
->grabrowcount
= 1;
180 cam
->grabrowcounttot
= cam
->grabrowcount
;
181 cam
->grabrowindex
= 0;
182 cam
->grabrowbatchsize
= 1;
183 cam
->grabrowbufferindex
= cam
->grabrowcount
;
184 cam
->flushcountbeforefirstrow
= 0;
185 cam
->flushcountafterlastrow
= 0;
190 long fli_camera_parport_get_array_area(flidev_t dev
, long *ul_x
, long *ul_y
,
191 long *lr_x
, long *lr_y
)
195 cam
= DEVICE
->device_data
;
197 *ul_x
= cam
->ccd
.array_area
.ul
.x
;
198 *ul_y
= cam
->ccd
.array_area
.ul
.y
;
199 *lr_x
= cam
->ccd
.array_area
.lr
.x
;
200 *lr_y
= cam
->ccd
.array_area
.lr
.y
;
205 long fli_camera_parport_get_visible_area(flidev_t dev
, long *ul_x
, long *ul_y
,
206 long *lr_x
, long *lr_y
)
210 cam
= DEVICE
->device_data
;
212 *ul_x
= cam
->ccd
.visible_area
.ul
.x
;
213 *ul_y
= cam
->ccd
.visible_area
.ul
.y
;
214 *lr_x
= cam
->ccd
.visible_area
.lr
.x
;
215 *lr_y
= cam
->ccd
.visible_area
.lr
.y
;
220 long fli_camera_parport_set_exposure_time(flidev_t dev
, long exptime
)
224 cam
= DEVICE
->device_data
;
229 cam
->exposure
= exptime
;
231 if (exptime
<= 15000) /* Less than thirty seconds..., 8.192e-3 sec */
234 cam
->expmul
= (long) (((double) exptime
) / 8.192);
236 else if (exptime
<= 2000000) /* Less than one hour */
238 cam
->expdur
= (long) (1.0 / 8.192e-3);
239 cam
->expmul
= (long) (exptime
/ 1000);
243 cam
->expdur
= (long) (10.0 / 8.192e-3);
244 cam
->expmul
= (long) (exptime
/ 10000);
250 long fli_camera_parport_set_image_area(flidev_t dev
, long ul_x
, long ul_y
,
251 long lr_x
, long lr_y
)
255 cam
= DEVICE
->device_data
;
257 if ((ul_x
< cam
->ccd
.visible_area
.ul
.x
) ||
258 (ul_y
< cam
->ccd
.visible_area
.ul
.y
) ||
259 (lr_x
> cam
->ccd
.visible_area
.lr
.x
) ||
260 (lr_y
> cam
->ccd
.visible_area
.lr
.y
))
263 cam
->image_area
.ul
.x
= ul_x
;
264 cam
->image_area
.ul
.y
= ul_y
;
265 cam
->image_area
.lr
.x
= lr_x
;
266 cam
->image_area
.lr
.y
= lr_y
;
271 long fli_camera_parport_set_hbin(flidev_t dev
, long hbin
)
275 cam
= DEVICE
->device_data
;
277 if ((hbin
< 1) || (hbin
> 16))
284 long fli_camera_parport_set_vbin(flidev_t dev
, long vbin
)
288 cam
= DEVICE
->device_data
;
290 if ((vbin
< 1) || (vbin
> 16))
297 long fli_camera_parport_get_exposure_status(flidev_t dev
, long *timeleft
)
303 cam
= DEVICE
->device_data
;
306 buf
= htons(C_SHUTTER(1,0));
307 IO(dev
, &buf
, &wlen
, &rlen
);
308 if ((ntohs(buf
) & 0xf000) != C_SHUTTER(0,0))
310 debug(FLIDEBUG_FAIL
, "(exposurestatus) echo back from camera failed.");
314 *timeleft
= (long)((double)(ntohs(buf
) & 0x07ff) *
315 ((double)cam
->expdur
* 8.192));
320 long fli_camera_parport_set_temperature(flidev_t dev
, double temperature
)
326 cam
= DEVICE
->device_data
;
329 buf
= (unsigned short)((temperature
- cam
->tempintercept
) /
331 buf
= htons((unsigned short) C_TEMP(buf
));
332 IO(dev
, &buf
, &wlen
, &rlen
);
333 if ((ntohs(buf
) & 0xf000) != C_TEMP(0))
335 debug(FLIDEBUG_FAIL
, "(settemperature) echo back from camera failed.");
342 long fli_camera_parport_get_temperature(flidev_t dev
, double *temperature
)
348 cam
= DEVICE
->device_data
;
351 buf
= htons(C_TEMP(0x0800));
352 IO(dev
, &buf
, &wlen
, &rlen
);
353 if ((ntohs(buf
) & 0xf000) != C_TEMP(0))
355 debug(FLIDEBUG_FAIL
, "(settemperature) echo back from camera failed.");
358 *temperature
= cam
->tempslope
* (double)(ntohs(buf
) & 0x00ff) +
364 long fli_camera_parport_grab_row(flidev_t dev
, void *buff
, size_t width
)
372 cam
= DEVICE
->device_data
;
374 if (cam
->flushcountbeforefirstrow
> 0)
376 if ((r
= fli_camera_parport_flush_rows(dev
,
377 cam
->flushcountbeforefirstrow
, 1)))
380 cam
->flushcountbeforefirstrow
= 0;
383 dTm
= (25.0e-6) * cam
->ccd
.array_area
.lr
.x
+ 1e-3;
385 cam
->readto
= (long)dTm
;
386 cam
->writeto
= (long)dTm
;
389 buf
= htons((unsigned short) C_SEND(cam
->grabrowwidth
));
390 IO(dev
, &buf
, &wlen
, &rlen
);
392 if (cam
->bitdepth
== FLI_MODE_8BIT
)
397 if ((cbuf
= xmalloc(cam
->grabrowwidth
)) == NULL
)
399 debug(FLIDEBUG_FAIL
, "Failed memory allocation during row grab.");
403 rlen
= cam
->grabrowwidth
; wlen
= 0;
404 r
= DEVICE
->fli_io(dev
, cbuf
, &wlen
, &rlen
);
407 debug(FLIDEBUG_WARN
, "Couldn't grab entire row, got %d of %d bytes.",
408 rlen
, cam
->grabrowwidth
);
410 for (x
= 0; x
< (int)width
; x
++)
412 ((char *)buff
)[x
] = (((cbuf
[x
]) + 128) & 0x00ff);
418 unsigned short *sbuf
;
421 if ((sbuf
= xmalloc(cam
->grabrowwidth
* sizeof(unsigned short))) == NULL
)
423 debug(FLIDEBUG_FAIL
, "Failed memory allocation during row grab.");
427 rlen
= cam
->grabrowwidth
* sizeof(unsigned short); wlen
= 0;
428 r
= DEVICE
->fli_io(dev
, sbuf
, &wlen
, &rlen
);
431 debug(FLIDEBUG_WARN
, "Couldn't grab entire row, got %d of %d bytes.",
432 rlen
, cam
->grabrowwidth
);
434 for (x
= 0; x
< (int)width
; x
++)
436 if (DEVICE
->devinfo
.hwrev
== 0x01) /* IMG camera */
438 ((unsigned short *)buff
)[x
] = ntohs(sbuf
[x
]) + 32768;
442 ((unsigned short *)buff
)[x
] = ntohs(sbuf
[x
]);
449 IO(dev
, &buf
, &wlen
, &rlen
);
450 if (ntohs(buf
) != C_SEND(width
))
452 debug(FLIDEBUG_WARN
, "Width: %d, requested %d.",
453 width
, cam
->grabrowwidth
* sizeof(unsigned short));
454 debug(FLIDEBUG_WARN
, "Got 0x%04x instead of 0x%04x.", ntohs(buf
), C_SEND(width
));
455 debug(FLIDEBUG_WARN
, "Didn't get command echo at end of row.");
458 if (cam
->grabrowcount
> 0)
461 if (cam
->grabrowcount
== 0)
463 if ((r
= fli_camera_parport_flush_rows(dev
,
464 cam
->flushcountafterlastrow
, 1)))
467 cam
->flushcountafterlastrow
= 0;
468 cam
->grabrowbatchsize
= 1;
478 long fli_camera_parport_expose_frame(flidev_t dev
)
484 cam
= DEVICE
->device_data
;
486 debug(FLIDEBUG_INFO
, "Setting X Row Offset.");
488 buf
= htons((unsigned short) D_XROWOFF(cam
->image_area
.ul
.x
));
489 IO(dev
, &buf
, &wlen
, &rlen
);
491 debug(FLIDEBUG_INFO
, "Setting X Row Width to %d.", cam
->ccd
.array_area
.lr
.x
- cam
->ccd
.array_area
.ul
.x
);
492 buf
= htons((unsigned short) D_XROWWID(cam
->ccd
.array_area
.lr
.x
- cam
->ccd
.array_area
.ul
.x
));
493 IO(dev
, &buf
, &wlen
, &rlen
);
495 debug(FLIDEBUG_INFO
, "Setting X Flush Bin.");
496 buf
= htons((unsigned short) D_XFLBIN(cam
->hflushbin
));
497 IO(dev
, &buf
, &wlen
, &rlen
);
499 debug(FLIDEBUG_INFO
, "Setting Y Flush Bin.");
500 buf
= htons((unsigned short) D_YFLBIN(cam
->vflushbin
));
501 IO(dev
, &buf
, &wlen
, &rlen
);
503 debug(FLIDEBUG_INFO
, "Setting X Bin.");
504 buf
= htons((unsigned short) D_XBIN(cam
->hbin
));
505 IO(dev
, &buf
, &wlen
, &rlen
);
507 debug(FLIDEBUG_INFO
, "Setting Y Bin.");
508 buf
= htons((unsigned short) D_YBIN(cam
->vbin
));
509 IO(dev
, &buf
, &wlen
, &rlen
);
511 debug(FLIDEBUG_INFO
, "Setting Exposure Duration.");
512 buf
= htons((unsigned short) D_EXPDUR(cam
->expdur
));
513 IO(dev
, &buf
, &wlen
, &rlen
);
515 if (cam
->bitdepth
== FLI_MODE_8BIT
)
517 debug(FLIDEBUG_INFO
, "Eight Bit.");
518 buf
= htons((unsigned short)((cam
->exttrigger
> 0) ?
519 C_RESTCFG(0,0,1,7) : C_RESTCFG(0,0,0,7)));
523 debug(FLIDEBUG_INFO
, "Sixteen Bit.");
524 buf
= htons((unsigned short)((cam
->exttrigger
> 0) ?
525 C_RESTCFG(0,0,1,15) :
526 C_RESTCFG(0,0,0,15)));
528 IO(dev
, &buf
, &wlen
, &rlen
);
530 if (cam
->flushes
> 0)
534 debug(FLIDEBUG_INFO
, "Flushing array.");
535 if ((r
= fli_camera_parport_flush_rows(dev
,
536 cam
->ccd
.array_area
.lr
.y
- cam
->ccd
.array_area
.ul
.y
,
541 debug(FLIDEBUG_INFO
, "Exposing.");
542 buf
= htons((unsigned short) C_SHUTTER((cam
->frametype
== FLI_FRAME_TYPE_DARK
)?0:1,
544 IO(dev
, &buf
, &wlen
, &rlen
);
546 cam
->grabrowwidth
= cam
->image_area
.lr
.x
- cam
->image_area
.ul
.x
;
547 cam
->flushcountbeforefirstrow
= cam
->image_area
.ul
.y
;
548 cam
->flushcountafterlastrow
=
549 (cam
->ccd
.array_area
.lr
.y
- cam
->ccd
.array_area
.ul
.y
) -
550 ((cam
->image_area
.lr
.y
- cam
->image_area
.ul
.y
) * cam
->vbin
) -
551 cam
->image_area
.ul
.y
;
553 if (cam
->flushcountafterlastrow
< 0)
554 cam
->flushcountafterlastrow
= 0;
556 cam
->grabrowcount
= cam
->image_area
.lr
.y
- cam
->image_area
.ul
.y
;
561 long fli_camera_parport_flush_rows(flidev_t dev
, long rows
, long repeat
)
574 cam
= DEVICE
->device_data
;
576 dTm
= ((25e-6) / (cam
->hflushbin
/ 2)) * cam
->ccd
.array_area
.lr
.x
+ 1e-3;
579 cam
->readto
= (long)dTm
;
580 cam
->writeto
= (long)dTm
;
587 buf
= htons((unsigned short) C_FLUSH(rows
));
588 retval
= DEVICE
->fli_io(dev
, &buf
, &wlen
, &rlen
);
601 long fli_camera_parport_set_bit_depth(flidev_t dev
, flibitdepth_t bitdepth
)
605 cam
= DEVICE
->device_data
;
607 if (DEVICE
->devinfo
.type
!= 0x01) /* IMG cameras only support this */
610 if ((bitdepth
!= FLI_MODE_8BIT
) && (bitdepth
!= FLI_MODE_16BIT
))
612 debug(FLIDEBUG_FAIL
, "Invalid bit depth setting.");
616 cam
->bitdepth
= bitdepth
;
621 static void correctioportdatawrite(flidev_t dev
, unsigned short *Data
)
627 switch(DEVICE
->devinfo
.hwrev
)
630 data
|= (*Data
& FLICCD_IO_P0
)?0x01:0;
631 data
|= (*Data
& FLICCD_IO_P1
)?0x02:0;
632 data
|= (*Data
& FLICCD_IO_P2
)?0x04:0;
633 data
|= (*Data
& FLICCD_IO_P3
)?0x80:0;
637 data
|= (*Data
& FLICCD_IO_P0
)?0x08:0;
638 data
|= (*Data
& FLICCD_IO_P1
)?0x10:0;
639 data
|= (*Data
& FLICCD_IO_P2
)?0x20:0;
640 data
|= (*Data
& FLICCD_IO_P3
)?0x40:0;
652 static void correctioportdataread(flidev_t dev
, unsigned short *Data
)
658 switch (DEVICE
->devinfo
.hwrev
)
661 data
|= (*Data
& 0x01)?FLICCD_IO_P0
:0;
662 data
|= (*Data
& 0x02)?FLICCD_IO_P1
:0;
663 data
|= (*Data
& 0x04)?FLICCD_IO_P2
:0;
664 data
|= (*Data
& 0x80)?FLICCD_IO_P3
:0;
668 data
|= (*Data
& 0x08)?FLICCD_IO_P0
:0;
669 data
|= (*Data
& 0x10)?FLICCD_IO_P1
:0;
670 data
|= (*Data
& 0x20)?FLICCD_IO_P2
:0;
671 data
|= (*Data
& 0x40)?FLICCD_IO_P3
:0;
683 long fli_camera_parport_read_ioport(flidev_t dev
, long *ioportset
)
690 IO(dev
, &buf
, &wlen
, &rlen
);
692 *ioportset
= ntohs(buf
) & 0x00ff;
693 correctioportdataread(dev
, (unsigned short *) ioportset
);
698 long fli_camera_parport_write_ioport(flidev_t dev
, long ioportset
)
701 unsigned short buf
= (unsigned short) ioportset
;
703 correctioportdatawrite(dev
, &buf
);
704 buf
= htons((unsigned short) (0x7100 | (buf
& 0x00ff)));
707 IO(dev
, &buf
, &wlen
, &rlen
);
712 long fli_camera_parport_configure_ioport(flidev_t dev
, long ioportset
)
715 unsigned short buf
= (unsigned short) ioportset
;
717 correctioportdatawrite(dev
, &buf
);
718 buf
= htons((unsigned short) (0x7000 | (buf
& 0x00ff)));
721 IO(dev
, &buf
, &wlen
, &rlen
);
726 long fli_camera_parport_control_shutter(flidev_t dev
, long shutter
)
732 buf
= htons(D_EXPDUR(0));
733 IO(dev
, &buf
, &wlen
, &rlen
);
737 case FLI_SHUTTER_CLOSE
:
738 debug(FLIDEBUG_INFO
, "Closing shutter.");
739 buf
= htons(C_SHUTTER(0, 0));
740 IO(dev
, &buf
, &wlen
, &rlen
);
743 case FLI_SHUTTER_OPEN
:
744 buf
= htons(C_SHUTTER(1, 1));
745 IO(dev
, &buf
, &wlen
, &rlen
);