You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
777 lines
20 KiB
777 lines
20 KiB
/*
|
|
|
|
Copyright (c) 2002 Finger Lakes Instrumentation (FLI), L.L.C.
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
|
|
Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
Redistributions in binary form must reproduce the above
|
|
copyright notice, this list of conditions and the following
|
|
disclaimer in the documentation and/or other materials
|
|
provided with the distribution.
|
|
|
|
Neither the name of Finger Lakes Instrumentation (FLI), LLC
|
|
nor the names of its contributors may be used to endorse or
|
|
promote products derived from this software without specific
|
|
prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
======================================================================
|
|
|
|
Finger Lakes Instrumentation, L.L.C. (FLI)
|
|
web: http://www.fli-cam.com
|
|
email: support@fli-cam.com
|
|
|
|
*/
|
|
|
|
#ifdef WIN32
|
|
#include <winsock.h>
|
|
#else
|
|
#include <sys/param.h>
|
|
#include <netinet/in.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include "libfli-libfli.h"
|
|
#include "libfli-debug.h"
|
|
#include "libfli-mem.h"
|
|
#include "libfli-camera.h"
|
|
#include "libfli-camera-usb.h"
|
|
|
|
double dconvert(void *buf)
|
|
{
|
|
unsigned char *fnum = (unsigned char *) buf;
|
|
double sign, exponent, mantissa, result;
|
|
|
|
sign = (double) ((fnum[3] & 0x80)?(-1):(1));
|
|
exponent = (double) ((fnum[3] & 0x7f) << 1 | ((fnum[2] & 0x80)?1:0));
|
|
|
|
mantissa = 1.0 +
|
|
((double) ((fnum[2] & 0x7f) << 16 | fnum[1] << 8 | fnum[0]) /
|
|
pow(2, 23));
|
|
|
|
result = sign * (double) pow(2, (exponent - 127.0)) * mantissa;
|
|
|
|
return result;
|
|
}
|
|
|
|
long fli_camera_usb_open(flidev_t dev)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[32];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
if ((cam->gbuf = xmalloc(USB_READ_SIZ_MAX)) == NULL)
|
|
return -ENOMEM;
|
|
|
|
buf[0] = htons(FLI_USBCAM_HARDWAREREV);
|
|
rlen = 2; wlen = 2;
|
|
IO(dev, buf, &wlen, &rlen);
|
|
DEVICE->devinfo.hwrev = ntohs(buf[0]);
|
|
|
|
buf[0] = htons(FLI_USBCAM_DEVICEID);
|
|
rlen = 2; wlen = 2;
|
|
IO(dev, buf, &wlen, &rlen);
|
|
DEVICE->devinfo.devid = ntohs(buf[0]);
|
|
|
|
buf[0] = htons(FLI_USBCAM_SERIALNUM);
|
|
rlen = 2; wlen = 2;
|
|
IO(dev, buf, &wlen, &rlen);
|
|
DEVICE->devinfo.serno = ntohs(buf[0]);
|
|
|
|
debug(FLIDEBUG_INFO, "DeviceID %d", DEVICE->devinfo.devid);
|
|
debug(FLIDEBUG_INFO, "SerialNum %d", DEVICE->devinfo.serno);
|
|
debug(FLIDEBUG_INFO, "HWRev %d", DEVICE->devinfo.hwrev);
|
|
debug(FLIDEBUG_INFO, "FWRev %d", DEVICE->devinfo.fwrev);
|
|
|
|
if (DEVICE->devinfo.fwrev < 0x0201)
|
|
{
|
|
int id;
|
|
|
|
for (id = 0; knowndev[id].index != 0; id++)
|
|
if (knowndev[id].index == DEVICE->devinfo.devid)
|
|
break;
|
|
|
|
if (knowndev[id].index == 0)
|
|
return -ENODEV;
|
|
|
|
cam->ccd.pixelwidth = knowndev[id].pixelwidth;
|
|
cam->ccd.pixelheight = knowndev[id].pixelheight;
|
|
|
|
wlen = sizeof(unsigned short) * 7;
|
|
rlen = 0;
|
|
buf[0] = htons(FLI_USBCAM_DEVINIT);
|
|
buf[1] = htons((unsigned short)knowndev[id].array_area.lr.x);
|
|
buf[2] = htons((unsigned short)knowndev[id].array_area.lr.y);
|
|
buf[3] = htons((unsigned short)(knowndev[id].visible_area.lr.x -
|
|
knowndev[id].visible_area.ul.x));
|
|
buf[4] = htons((unsigned short)(knowndev[id].visible_area.lr.y -
|
|
knowndev[id].visible_area.ul.y));
|
|
buf[5] = htons((unsigned short)knowndev[id].visible_area.ul.x);
|
|
buf[6] = htons((unsigned short)knowndev[id].visible_area.ul.y);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
if ((DEVICE->devinfo.model =
|
|
(char *)xmalloc(strlen(knowndev[id].model) + 1)) == NULL)
|
|
return -ENOMEM;
|
|
strcpy(DEVICE->devinfo.model, knowndev[id].model);
|
|
|
|
switch(DEVICE->devinfo.fwrev & 0xff00)
|
|
{
|
|
case 0x0100:
|
|
cam->tempslope = (70.0 / 215.75);
|
|
cam->tempintercept = (-52.5681);
|
|
break;
|
|
|
|
case 0x0200:
|
|
cam->tempslope = (100.0 / 201.1);
|
|
cam->tempintercept = (-61.613);
|
|
break;
|
|
|
|
default:
|
|
cam->tempslope = 1e-12;
|
|
cam->tempintercept = 0;
|
|
}
|
|
}
|
|
else if (DEVICE->devinfo.fwrev >= 0x0201) /* Here, all the parameters are stored on the camera */
|
|
{
|
|
rlen = 64; wlen = 2;
|
|
buf[0] = htons(FLI_USBCAM_READPARAMBLOCK);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
cam->ccd.pixelwidth = dconvert((char *) ((void *)buf) + 31);
|
|
cam->ccd.pixelheight = dconvert((char*) ((void *)buf) + 35);
|
|
cam->tempslope = dconvert((char *) ((void *)buf) + 23);
|
|
cam->tempintercept = dconvert((char *) ((void *)buf) + 27);
|
|
}
|
|
|
|
rlen = 32; wlen = 2;
|
|
buf[0] = htons(FLI_USBCAM_DEVICENAME);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
if ((DEVICE->devinfo.devnam = (char *)xmalloc(rlen + 1)) == NULL)
|
|
return -ENOMEM;
|
|
memcpy(DEVICE->devinfo.devnam, buf, rlen);
|
|
DEVICE->devinfo.devnam[rlen] = '\0';
|
|
|
|
if(DEVICE->devinfo.model == NULL)
|
|
{
|
|
DEVICE->devinfo.model = xstrdup(DEVICE->devinfo.devnam);
|
|
}
|
|
|
|
rlen = 4; wlen = 2;
|
|
buf[0] = htons(FLI_USBCAM_ARRAYSIZE);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
cam->ccd.array_area.ul.x = 0;
|
|
cam->ccd.array_area.ul.y = 0;
|
|
cam->ccd.array_area.lr.x = ntohs(buf[0]);
|
|
cam->ccd.array_area.lr.y = ntohs(buf[1]);
|
|
|
|
rlen = 4; wlen = 2;
|
|
buf[0] = htons(FLI_USBCAM_IMAGEOFFSET);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
cam->ccd.visible_area.ul.x = ntohs(buf[0]);
|
|
cam->ccd.visible_area.ul.y = ntohs(buf[1]);
|
|
|
|
rlen = 4; wlen = 2;
|
|
buf[0] = htons(FLI_USBCAM_IMAGESIZE);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
cam->ccd.visible_area.lr.x = cam->ccd.visible_area.ul.x + ntohs(buf[0]);
|
|
cam->ccd.visible_area.lr.y = cam->ccd.visible_area.ul.y + ntohs(buf[1]);
|
|
|
|
debug(FLIDEBUG_INFO, " Name: %s", DEVICE->devinfo.devnam);
|
|
debug(FLIDEBUG_INFO, " Array: (%4d,%4d),(%4d,%4d)",
|
|
cam->ccd.array_area.ul.x,
|
|
cam->ccd.array_area.ul.y,
|
|
cam->ccd.array_area.lr.x,
|
|
cam->ccd.array_area.lr.y);
|
|
debug(FLIDEBUG_INFO, " Visible: (%4d,%4d),(%4d,%4d)",
|
|
cam->ccd.visible_area.ul.x,
|
|
cam->ccd.visible_area.ul.y,
|
|
cam->ccd.visible_area.lr.x,
|
|
cam->ccd.visible_area.lr.y);
|
|
|
|
debug(FLIDEBUG_INFO, " Pix Size: (%g, %g)", cam->ccd.pixelwidth, cam->ccd.pixelheight);
|
|
debug(FLIDEBUG_INFO, " Temp.: T = AD x %g + %g", cam->tempslope, cam->tempintercept);
|
|
|
|
/* Initialize all varaibles to something */
|
|
|
|
cam->vflushbin = 4;
|
|
cam->hflushbin = 4;
|
|
cam->vbin = 1;
|
|
cam->hbin = 1;
|
|
cam->image_area.ul.x = cam->ccd.visible_area.ul.x;
|
|
cam->image_area.ul.y = cam->ccd.visible_area.ul.y;
|
|
cam->image_area.lr.x = cam->ccd.visible_area.lr.x;
|
|
cam->image_area.lr.y = cam->ccd.visible_area.lr.y;
|
|
cam->exposure = 100;
|
|
cam->frametype = FLI_FRAME_TYPE_NORMAL;
|
|
cam->flushes = 0;
|
|
cam->bitdepth = FLI_MODE_16BIT;
|
|
cam->exttrigger = 0;
|
|
cam->exttriggerpol = 0;
|
|
|
|
cam->grabrowwidth =
|
|
(cam->image_area.lr.x - cam->image_area.ul.x) / cam->hbin;
|
|
cam->grabrowcount = 1;
|
|
cam->grabrowcounttot = cam->grabrowcount;
|
|
cam->grabrowindex = 0;
|
|
cam->grabrowbatchsize = 1;
|
|
cam->grabrowbufferindex = cam->grabrowcount;
|
|
cam->flushcountbeforefirstrow = 0;
|
|
cam->flushcountafterlastrow = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_get_array_area(flidev_t dev, long *ul_x, long *ul_y,
|
|
long *lr_x, long *lr_y)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
rlen = 4; wlen = 2;
|
|
buf[0] = htons(FLI_USBCAM_ARRAYSIZE);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
cam->ccd.array_area.ul.x = 0;
|
|
cam->ccd.array_area.ul.y = 0;
|
|
cam->ccd.array_area.lr.x = ntohs(buf[0]);
|
|
cam->ccd.array_area.lr.y = ntohs(buf[1]);
|
|
|
|
*ul_x = cam->ccd.array_area.ul.x;
|
|
*ul_y = cam->ccd.array_area.ul.y;
|
|
*lr_x = cam->ccd.array_area.lr.x;
|
|
*lr_y = cam->ccd.array_area.lr.y;
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_get_visible_area(flidev_t dev, long *ul_x, long *ul_y,
|
|
long *lr_x, long *lr_y)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
rlen = 4; wlen = 2;
|
|
buf[0] = htons(FLI_USBCAM_IMAGEOFFSET);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
cam->ccd.visible_area.ul.x = ntohs(buf[0]);
|
|
cam->ccd.visible_area.ul.y = ntohs(buf[1]);
|
|
|
|
rlen = 4; wlen = 2;
|
|
buf[0] = htons(FLI_USBCAM_IMAGESIZE);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
cam->ccd.visible_area.lr.x = cam->ccd.visible_area.ul.x + ntohs(buf[0]);
|
|
cam->ccd.visible_area.lr.y = cam->ccd.visible_area.ul.y + ntohs(buf[1]);
|
|
|
|
*ul_x = cam->ccd.visible_area.ul.x;
|
|
*ul_y = cam->ccd.visible_area.ul.y;
|
|
*lr_x = cam->ccd.visible_area.lr.x;
|
|
*lr_y = cam->ccd.visible_area.lr.y;
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_set_exposure_time(flidev_t dev, long exptime)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
if (exptime < 0)
|
|
return -EINVAL;
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
rlen = 0; wlen = 8;
|
|
buf[0] = htons(FLI_USBCAM_SETEXPOSURE);
|
|
((unsigned long *)((void *) buf))[1] = htonl(exptime);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
cam->exposure = exptime;
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_set_image_area(flidev_t dev, long ul_x, long ul_y,
|
|
long lr_x, long lr_y)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
if( (DEVICE->devinfo.fwrev < 0x0300) &&
|
|
((DEVICE->devinfo.hwrev & 0xff00) == 0x0100) )
|
|
{
|
|
if( (lr_x > (cam->ccd.visible_area.lr.x * cam->hbin)) ||
|
|
(lr_y > (cam->ccd.visible_area.lr.y * cam->vbin)) )
|
|
{
|
|
debug(FLIDEBUG_WARN,
|
|
"FLISetVisibleArea(), area out of bounds: (%4d,%4d),(%4d,%4d)",
|
|
ul_x, ul_y, lr_x, lr_y);
|
|
}
|
|
}
|
|
|
|
if( (ul_x < cam->ccd.visible_area.ul.x) ||
|
|
(ul_y < cam->ccd.visible_area.ul.y) )
|
|
{
|
|
debug(FLIDEBUG_FAIL,
|
|
"FLISetVisibleArea(), area out of bounds: (%4d,%4d),(%4d,%4d)",
|
|
ul_x, ul_y, lr_x, lr_y);
|
|
return -EINVAL;
|
|
}
|
|
|
|
rlen = 0; wlen = 6;
|
|
buf[0] = htons(FLI_USBCAM_SETFRAMEOFFSET);
|
|
buf[1] = htons((unsigned short) cam->image_area.ul.x);
|
|
buf[2] = htons((unsigned short) cam->image_area.ul.y);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
cam->image_area.ul.x = ul_x;
|
|
cam->image_area.ul.y = ul_y;
|
|
cam->image_area.lr.x = lr_x;
|
|
cam->image_area.lr.y = lr_y;
|
|
cam->grabrowwidth =
|
|
(cam->image_area.lr.x - cam->image_area.ul.x) / cam->hbin;
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_set_hbin(flidev_t dev, long hbin)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
if ((hbin < 1) || (hbin > 16))
|
|
return -EINVAL;
|
|
|
|
rlen = 0; wlen = 6;
|
|
buf[0] = htons(FLI_USBCAM_SETBINFACTORS);
|
|
buf[1] = htons((unsigned short) hbin);
|
|
buf[2] = htons((unsigned short) cam->vbin);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
cam->hbin = hbin;
|
|
cam->grabrowwidth =
|
|
(cam->image_area.lr.x - cam->image_area.ul.x) / cam->hbin;
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_set_vbin(flidev_t dev, long vbin)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
if ((vbin < 1) || (vbin > 16))
|
|
return -EINVAL;
|
|
|
|
rlen = 0; wlen = 6;
|
|
buf[0] = htons(FLI_USBCAM_SETBINFACTORS);
|
|
buf[1] = htons((unsigned short) cam->hbin);
|
|
buf[2] = htons((unsigned short) vbin);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
cam->vbin = vbin;
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_get_exposure_status(flidev_t dev, long *timeleft)
|
|
{
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
rlen = 4; wlen = 2;
|
|
buf[0] = htons(FLI_USBCAM_EXPOSURESTATUS);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
*timeleft = ntohl(((unsigned long *)((void *) buf))[0]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_set_temperature(flidev_t dev, double temperature)
|
|
{
|
|
flicamdata_t *cam;
|
|
unsigned short ad;
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
if(DEVICE->devinfo.fwrev < 0x0200)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if(cam->tempslope == 0.0)
|
|
{
|
|
ad = 255;
|
|
}
|
|
else
|
|
{
|
|
ad = (unsigned short) ((temperature - cam->tempintercept) / cam->tempslope);
|
|
}
|
|
|
|
debug(FLIDEBUG_INFO, "Temperature slope, intercept, AD val, %f %f %f %d", temperature, cam->tempslope, cam->tempintercept, ad);
|
|
|
|
rlen = 0; wlen = 4;
|
|
buf[0] = htons(FLI_USBCAM_TEMPERATURE);
|
|
buf[1] = htons(ad);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_get_temperature(flidev_t dev, double *temperature)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[16];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
rlen = 2; wlen = 2;
|
|
buf[0] = htons(FLI_USBCAM_TEMPERATURE);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
*temperature = cam->tempslope * (double)((ntohs(buf[0]) & 0x00ff)) +
|
|
cam->tempintercept;
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_grab_row(flidev_t dev, void *buff, size_t width)
|
|
{
|
|
flicamdata_t *cam;
|
|
long x;
|
|
long r;
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
if(width > (size_t) (cam->image_area.lr.x - cam->image_area.ul.x))
|
|
{
|
|
debug(FLIDEBUG_FAIL, "FLIGrabRow(), requested row too wide.");
|
|
debug(FLIDEBUG_FAIL, " Requested width: %d", width);
|
|
debug(FLIDEBUG_FAIL, " FLISetImageArea() width: %d",
|
|
cam->image_area.lr.x - cam->image_area.ul.x);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (cam->flushcountbeforefirstrow > 0)
|
|
{
|
|
if ((r = fli_camera_usb_flush_rows(dev, cam->flushcountbeforefirstrow, 1)))
|
|
return r;
|
|
|
|
cam->flushcountbeforefirstrow = 0;
|
|
}
|
|
|
|
if (cam->grabrowbufferindex >= cam->grabrowbatchsize)
|
|
{
|
|
/* We don't have the row in memory */
|
|
long rlen, wlen;
|
|
|
|
/* Do we have less than GrabRowBatchSize rows to grab? */
|
|
if (cam->grabrowbatchsize > (cam->grabrowcounttot - cam->grabrowindex))
|
|
{
|
|
cam->grabrowbatchsize = cam->grabrowcounttot - cam->grabrowindex;
|
|
}
|
|
|
|
rlen = cam->grabrowwidth * 2 * cam->grabrowbatchsize;
|
|
wlen = 6;
|
|
cam->gbuf[0] = htons(FLI_USBCAM_SENDROW);
|
|
cam->gbuf[1] = htons((unsigned short) cam->grabrowwidth);
|
|
cam->gbuf[2] = htons((unsigned short) cam->grabrowbatchsize);
|
|
IO(dev, cam->gbuf, &wlen, &rlen);
|
|
|
|
for (x = 0; x < (cam->grabrowwidth * cam->grabrowbatchsize); x++)
|
|
{
|
|
if ((DEVICE->devinfo.hwrev & 0xff00) == 0x0100)
|
|
{
|
|
cam->gbuf[x] = ntohs(cam->gbuf[x]) + 32768;
|
|
}
|
|
else
|
|
{
|
|
cam->gbuf[x] = ntohs(cam->gbuf[x]);
|
|
}
|
|
}
|
|
cam->grabrowbufferindex = 0;
|
|
}
|
|
|
|
for (x = 0; x < (long)width; x++)
|
|
{
|
|
((unsigned short *)buff)[x] =
|
|
cam->gbuf[x + (cam->grabrowbufferindex * cam->grabrowwidth)];
|
|
}
|
|
|
|
cam->grabrowbufferindex++;
|
|
cam->grabrowindex++;
|
|
|
|
if (cam->grabrowcount > 0)
|
|
{
|
|
cam->grabrowcount--;
|
|
if (cam->grabrowcount == 0)
|
|
{
|
|
if ((r = fli_camera_usb_flush_rows(dev, cam->flushcountafterlastrow, 1)))
|
|
return r;
|
|
|
|
cam->flushcountafterlastrow = 0;
|
|
cam->grabrowbatchsize = 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_expose_frame(flidev_t dev)
|
|
{
|
|
flicamdata_t *cam;
|
|
short flags = 0;
|
|
long rlen, wlen;
|
|
unsigned short buf[16];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
rlen = 0; wlen = 6;
|
|
buf[0] = htons(FLI_USBCAM_SETFRAMEOFFSET);
|
|
buf[1] = htons((unsigned short) cam->image_area.ul.x);
|
|
buf[2] = htons((unsigned short) cam->image_area.ul.y);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
rlen = 0; wlen = 6;
|
|
buf[0] = htons(FLI_USBCAM_SETBINFACTORS);
|
|
buf[1] = htons((unsigned short) cam->hbin);
|
|
buf[2] = htons((unsigned short) cam->vbin);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
rlen = 0; wlen = 6;
|
|
buf[0] = htons(FLI_USBCAM_SETFLUSHBINFACTORS);
|
|
buf[1] = htons((unsigned short) cam->hflushbin);
|
|
buf[2] = htons((unsigned short) cam->vflushbin);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
rlen = 0; wlen = 8;
|
|
buf[0] = htons(FLI_USBCAM_SETEXPOSURE);
|
|
((unsigned long *)((void *) buf))[1] = htonl(cam->exposure);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
/* What flags do we need to send... */
|
|
/* Dark Frame */
|
|
flags |= (cam->frametype == FLI_FRAME_TYPE_DARK) ? 0x01 : 0x00;
|
|
/* External trigger */
|
|
flags |= (cam->exttrigger != 0) ? 0x04 : 0x00;
|
|
flags |= (cam->exttriggerpol != 0) ? 0x08 : 0x00;
|
|
|
|
debug(FLIDEBUG_INFO, "Exposure flags: %04x", flags);
|
|
|
|
debug(FLIDEBUG_INFO, "Flushing %d times.\n", cam->flushes);
|
|
if (cam->flushes > 0)
|
|
{
|
|
long r;
|
|
|
|
if ((r = fli_camera_usb_flush_rows(dev,
|
|
cam->ccd.array_area.lr.y - cam->ccd.array_area.ul.y,
|
|
cam->flushes)))
|
|
return r;
|
|
}
|
|
|
|
rlen = 0; wlen = 4;
|
|
buf[0] = htons(FLI_USBCAM_STARTEXPOSURE);
|
|
buf[1] = htons((unsigned short) flags);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
cam->grabrowcount = cam->image_area.lr.y - cam->image_area.ul.y;
|
|
cam->grabrowcounttot = cam->grabrowcount;
|
|
cam->grabrowwidth = cam->image_area.lr.x - cam->image_area.ul.x;
|
|
cam->grabrowindex = 0;
|
|
cam->grabrowbatchsize = USB_READ_SIZ_MAX / (cam->grabrowwidth * 2);
|
|
|
|
/* Lets put some bounds on this... */
|
|
if (cam->grabrowbatchsize > cam->grabrowcounttot)
|
|
cam->grabrowbatchsize = cam->grabrowcounttot;
|
|
|
|
if (cam->grabrowbatchsize > 64)
|
|
cam->grabrowbatchsize = 64;
|
|
|
|
/* We need to get a whole new buffer by default */
|
|
cam->grabrowbufferindex = cam->grabrowbatchsize;
|
|
|
|
cam->flushcountbeforefirstrow = cam->image_area.ul.y;
|
|
cam->flushcountafterlastrow =
|
|
(cam->ccd.array_area.lr.y - cam->ccd.array_area.ul.y) -
|
|
((cam->image_area.lr.y - cam->image_area.ul.y) * cam->vbin) -
|
|
cam->image_area.ul.y;
|
|
|
|
if (cam->flushcountbeforefirstrow < 0)
|
|
cam->flushcountbeforefirstrow = 0;
|
|
|
|
if (cam->flushcountafterlastrow < 0)
|
|
cam->flushcountafterlastrow = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_flush_rows(flidev_t dev, long rows, long repeat)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[16];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
if (rows < 0)
|
|
return -EINVAL;
|
|
|
|
if (rows == 0)
|
|
return 0;
|
|
|
|
rlen = 0; wlen = 6;
|
|
buf[0] = htons(FLI_USBCAM_SETFLUSHBINFACTORS);
|
|
buf[1] = htons((unsigned short) cam->hflushbin);
|
|
buf[2] = htons((unsigned short) cam->vflushbin);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
while (repeat > 0)
|
|
{
|
|
rlen = 0; wlen = 4;
|
|
buf[0] = htons(FLI_USBCAM_FLUSHROWS);
|
|
buf[1] = htons((unsigned short) rows);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
repeat--;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_set_bit_depth(flidev_t dev, flibitdepth_t bitdepth)
|
|
{
|
|
dev=dev; bitdepth=bitdepth;
|
|
return -EINVAL;
|
|
}
|
|
|
|
long fli_camera_usb_read_ioport(flidev_t dev, long *ioportset)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
rlen = 1; wlen = 2;
|
|
buf[0] = htons(FLI_USBCAM_READIO);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
*ioportset = ((unsigned char *)(void *)buf)[0];
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_write_ioport(flidev_t dev, long ioportset)
|
|
{
|
|
flicamdata_t *cam;
|
|
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
rlen = 0; wlen = 3;
|
|
buf[0] = htons(FLI_USBCAM_WRITEIO);
|
|
((unsigned char *)(void *)buf)[2] = (char)ioportset;
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_configure_ioport(flidev_t dev, long ioportset)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
rlen = 0; wlen = 3;
|
|
buf[0] = htons(FLI_USBCAM_WRITEDIR);
|
|
((unsigned char *)(void *)buf)[2] = (char)ioportset;
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_control_shutter(flidev_t dev, long shutter)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
rlen = 0; wlen = 3;
|
|
buf[0] = htons(FLI_USBCAM_SHUTTER);
|
|
((unsigned char *)(void *)buf)[2] = (char)shutter;
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
return 0;
|
|
}
|
|
|
|
long fli_camera_usb_control_bgflush(flidev_t dev, long bgflush)
|
|
{
|
|
flicamdata_t *cam;
|
|
long rlen, wlen;
|
|
unsigned short buf[8];
|
|
|
|
cam = DEVICE->device_data;
|
|
|
|
if(DEVICE->devinfo.fwrev < 0x0300)
|
|
{
|
|
debug(FLIDEBUG_WARN, "Background flush commanded on early firmware.");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if( (bgflush != FLI_BGFLUSH_STOP) &&
|
|
(bgflush != FLI_BGFLUSH_START) )
|
|
return -EINVAL;
|
|
|
|
rlen = 0; wlen = 4;
|
|
buf[0] = htons(FLI_USBCAM_BGFLUSH);
|
|
buf[1] = htons((unsigned short) bgflush);
|
|
IO(dev, buf, &wlen, &rlen);
|
|
|
|
return 0;
|
|
}
|