summaryrefslogtreecommitdiffstats
path: root/kstars/kstars/indi
diff options
context:
space:
mode:
Diffstat (limited to 'kstars/kstars/indi')
-rw-r--r--kstars/kstars/indi/INDI.dtd128
-rw-r--r--kstars/kstars/indi/LICENSE504
-rw-r--r--kstars/kstars/indi/Makefile.am82
-rw-r--r--kstars/kstars/indi/README103
-rw-r--r--kstars/kstars/indi/SchedGUI70
-rw-r--r--kstars/kstars/indi/apmount.cpp1660
-rw-r--r--kstars/kstars/indi/apmount.h144
-rw-r--r--kstars/kstars/indi/apogee/Apn.h56
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData.cpp130
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData.h124
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD3011HS.cpp582
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD3011HS.h50
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD3011LS.cpp572
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD3011LS.h41
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4020HS.h1
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4240HS.cpp572
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4240HS.h49
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4240LS.cpp572
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4240LS.h49
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4710HS.cpp566
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4710HS.h49
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4710LS.cpp572
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4710LS.h49
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4710LS2.cpp572
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4710LS2.h49
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4710LS3.cpp571
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4710LS3.h49
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4710LS4.cpp571
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4710LS4.h49
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4710LS5.cpp571
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4710LS5.h49
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4720HS.cpp550
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4720HS.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4720LS.cpp550
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD4720LS.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD5520HS.cpp572
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD5520HS.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD5520LS.cpp572
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD5520LS.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD5710HS.cpp550
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD5710HS.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD5710LS.cpp550
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD5710LS.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD7700HS.cpp554
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD7700HS.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD7700LS.cpp554
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_CCD7700LS.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF0261E.cpp615
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF0261E.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF0401E.cpp615
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF0401E.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF1001E.cpp615
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF1001E.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF1301E.cpp615
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF1301E.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF1401E.cpp615
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF1401E.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF1602E.cpp615
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF1602E.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF16801E.cpp619
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF16801E.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF3200E.cpp611
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF3200E.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF4202.cpp615
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF4202.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF6303E.cpp615
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_KAF6303E.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_TH7899.cpp609
-rw-r--r--kstars/kstars/indi/apogee/ApnCamData_TH7899.h47
-rw-r--r--kstars/kstars/indi/apogee/ApnCamTable.cpp149
-rw-r--r--kstars/kstars/indi/apogee/ApnCamTable.h125
-rw-r--r--kstars/kstars/indi/apogee/ApnCamera.cpp1890
-rw-r--r--kstars/kstars/indi/apogee/ApnCamera.h332
-rw-r--r--kstars/kstars/indi/apogee/ApnCamera_Linux.cpp129
-rw-r--r--kstars/kstars/indi/apogee/ApnCamera_NET.cpp275
-rw-r--r--kstars/kstars/indi/apogee/ApnCamera_NET.h74
-rw-r--r--kstars/kstars/indi/apogee/ApnCamera_USB.cpp256
-rw-r--r--kstars/kstars/indi/apogee/ApnCamera_USB.h69
-rw-r--r--kstars/kstars/indi/apogee/ApnSerial.cpp27
-rw-r--r--kstars/kstars/indi/apogee/ApnSerial.h60
-rw-r--r--kstars/kstars/indi/apogee/ApnSerial_NET.cpp214
-rw-r--r--kstars/kstars/indi/apogee/ApnSerial_NET.h52
-rw-r--r--kstars/kstars/indi/apogee/ApnSerial_USB.cpp79
-rw-r--r--kstars/kstars/indi/apogee/ApnSerial_USB.h43
-rw-r--r--kstars/kstars/indi/apogee/ApnUsbSys.h46
-rw-r--r--kstars/kstars/indi/apogee/Apogee.h97
-rw-r--r--kstars/kstars/indi/apogee/ApogeeIoctl.h40
-rw-r--r--kstars/kstars/indi/apogee/ApogeeLinux.h53
-rw-r--r--kstars/kstars/indi/apogee/ApogeeUsb.h86
-rw-r--r--kstars/kstars/indi/apogee/ApogeeUsbErr.h29
-rw-r--r--kstars/kstars/indi/apogee/ApogeeUsbLinux.cpp394
-rw-r--r--kstars/kstars/indi/apogee/ApogeeUsbLinuxForKernel.cpp486
-rw-r--r--kstars/kstars/indi/apogee/CameraIO_Linux.cpp1362
-rw-r--r--kstars/kstars/indi/apogee/CameraIO_Linux.h416
-rw-r--r--kstars/kstars/indi/apogee/CameraIO_LinuxISA.cpp319
-rw-r--r--kstars/kstars/indi/apogee/CameraIO_LinuxPCI.cpp373
-rw-r--r--kstars/kstars/indi/apogee/CameraIO_LinuxPPI.cpp325
-rw-r--r--kstars/kstars/indi/apogee/CameraIO_PCI.cpp405
-rw-r--r--kstars/kstars/indi/apogee/CameraIO_PCI.h35
-rw-r--r--kstars/kstars/indi/apogee/Camera_Example.cpp631
-rw-r--r--kstars/kstars/indi/apogee/FpgaRegs.h190
-rw-r--r--kstars/kstars/indi/apogee/Makefile.am22
-rw-r--r--kstars/kstars/indi/apogee/reb1100.cpp195
-rw-r--r--kstars/kstars/indi/apogee/stdafx.h38
-rw-r--r--kstars/kstars/indi/apogee_caminfo.xml40
-rw-r--r--kstars/kstars/indi/apogee_ppi.cpp1524
-rw-r--r--kstars/kstars/indi/apogee_ppi.h167
-rw-r--r--kstars/kstars/indi/base64.c245
-rw-r--r--kstars/kstars/indi/base64.h36
-rw-r--r--kstars/kstars/indi/celestrongps.cpp778
-rw-r--r--kstars/kstars/indi/celestrongps.h68
-rw-r--r--kstars/kstars/indi/celestronprotocol.c795
-rw-r--r--kstars/kstars/indi/celestronprotocol.h134
-rw-r--r--kstars/kstars/indi/drivers.xml111
-rw-r--r--kstars/kstars/indi/eventloop.c424
-rw-r--r--kstars/kstars/indi/eventloop.h110
-rw-r--r--kstars/kstars/indi/fitsrw.c2092
-rw-r--r--kstars/kstars/indi/fitsrw.h283
-rw-r--r--kstars/kstars/indi/fli/Makefile.am24
-rw-r--r--kstars/kstars/indi/fli/fli_ioctl.h119
-rw-r--r--kstars/kstars/indi/fli/libfli-camera-parport.c753
-rw-r--r--kstars/kstars/indi/fli/libfli-camera-parport.h102
-rw-r--r--kstars/kstars/indi/fli/libfli-camera-usb.c776
-rw-r--r--kstars/kstars/indi/fli/libfli-camera-usb.h98
-rw-r--r--kstars/kstars/indi/fli/libfli-camera.c790
-rw-r--r--kstars/kstars/indi/fli/libfli-camera.h111
-rw-r--r--kstars/kstars/indi/fli/libfli-debug.c120
-rw-r--r--kstars/kstars/indi/fli/libfli-debug.h53
-rw-r--r--kstars/kstars/indi/fli/libfli-filter-focuser.c625
-rw-r--r--kstars/kstars/indi/fli/libfli-filter-focuser.h74
-rw-r--r--kstars/kstars/indi/fli/libfli-libfli.h199
-rw-r--r--kstars/kstars/indi/fli/libfli-mem.c203
-rw-r--r--kstars/kstars/indi/fli/libfli-mem.h54
-rw-r--r--kstars/kstars/indi/fli/libfli-parport.c136
-rw-r--r--kstars/kstars/indi/fli/libfli-parport.h64
-rw-r--r--kstars/kstars/indi/fli/libfli-serial.c189
-rw-r--r--kstars/kstars/indi/fli/libfli-serial.h51
-rw-r--r--kstars/kstars/indi/fli/libfli-sys.c481
-rw-r--r--kstars/kstars/indi/fli/libfli-sys.h108
-rw-r--r--kstars/kstars/indi/fli/libfli-usb-sys-bsd.c133
-rw-r--r--kstars/kstars/indi/fli/libfli-usb-sys-linux.c225
-rw-r--r--kstars/kstars/indi/fli/libfli-usb-sys-null.c67
-rw-r--r--kstars/kstars/indi/fli/libfli-usb.c94
-rw-r--r--kstars/kstars/indi/fli/libfli-usb.h69
-rw-r--r--kstars/kstars/indi/fli/libfli.c1383
-rw-r--r--kstars/kstars/indi/fli/libfli.h214
-rw-r--r--kstars/kstars/indi/fli/libfli.pdfbin0 -> 110777 bytes
-rw-r--r--kstars/kstars/indi/fli/readme.txt15
-rw-r--r--kstars/kstars/indi/fli_ccd.c1435
-rw-r--r--kstars/kstars/indi/fli_wheel.c700
-rw-r--r--kstars/kstars/indi/fq.c208
-rw-r--r--kstars/kstars/indi/fq.h17
-rw-r--r--kstars/kstars/indi/indi_lpi.cpp146
-rw-r--r--kstars/kstars/indi/indi_philips.cpp75
-rw-r--r--kstars/kstars/indi/indi_v4l.cpp75
-rw-r--r--kstars/kstars/indi/indiapi.h363
-rw-r--r--kstars/kstars/indi/indicom.c638
-rw-r--r--kstars/kstars/indi/indicom.h272
-rw-r--r--kstars/kstars/indi/indidevapi.h511
-rw-r--r--kstars/kstars/indi/indidrivermain.c1250
-rw-r--r--kstars/kstars/indi/indiserver.c878
-rw-r--r--kstars/kstars/indi/lilxml.c762
-rw-r--r--kstars/kstars/indi/lilxml.h252
-rw-r--r--kstars/kstars/indi/lx200_16.cpp396
-rw-r--r--kstars/kstars/indi/lx200_16.h53
-rw-r--r--kstars/kstars/indi/lx200autostar.cpp154
-rw-r--r--kstars/kstars/indi/lx200autostar.h45
-rw-r--r--kstars/kstars/indi/lx200basic.cpp839
-rw-r--r--kstars/kstars/indi/lx200basic.h109
-rw-r--r--kstars/kstars/indi/lx200classic.cpp333
-rw-r--r--kstars/kstars/indi/lx200classic.h49
-rw-r--r--kstars/kstars/indi/lx200driver.c1386
-rw-r--r--kstars/kstars/indi/lx200driver.h247
-rw-r--r--kstars/kstars/indi/lx200generic.cpp2033
-rw-r--r--kstars/kstars/indi/lx200generic.h91
-rw-r--r--kstars/kstars/indi/lx200gps.cpp340
-rw-r--r--kstars/kstars/indi/lx200gps.h45
-rw-r--r--kstars/kstars/indi/sbigccd.cpp884
-rw-r--r--kstars/kstars/indi/sbigccd.h147
-rw-r--r--kstars/kstars/indi/skycommander.c185
-rw-r--r--kstars/kstars/indi/temmadriver.c1000
-rw-r--r--kstars/kstars/indi/temmadriver.h252
-rw-r--r--kstars/kstars/indi/v4ldriver.cpp875
-rw-r--r--kstars/kstars/indi/v4ldriver.h171
-rw-r--r--kstars/kstars/indi/v4lphilips.cpp610
-rw-r--r--kstars/kstars/indi/v4lphilips.h77
-rw-r--r--kstars/kstars/indi/webcam/Makefile.am16
-rw-r--r--kstars/kstars/indi/webcam/PPort.cpp107
-rw-r--r--kstars/kstars/indi/webcam/PPort.h75
-rw-r--r--kstars/kstars/indi/webcam/ccvt.h164
-rw-r--r--kstars/kstars/indi/webcam/ccvt_c2.c118
-rw-r--r--kstars/kstars/indi/webcam/ccvt_misc.c435
-rw-r--r--kstars/kstars/indi/webcam/ccvt_types.h60
-rw-r--r--kstars/kstars/indi/webcam/port.cpp199
-rw-r--r--kstars/kstars/indi/webcam/port.h122
-rw-r--r--kstars/kstars/indi/webcam/pwc-ioctl.h176
-rw-r--r--kstars/kstars/indi/webcam/v4l1_base.cpp564
-rw-r--r--kstars/kstars/indi/webcam/v4l1_base.h110
-rw-r--r--kstars/kstars/indi/webcam/v4l1_pwc.cpp563
-rw-r--r--kstars/kstars/indi/webcam/v4l1_pwc.h89
-rw-r--r--kstars/kstars/indi/webcam/v4l2_base.cpp1189
-rw-r--r--kstars/kstars/indi/webcam/v4l2_base.h141
-rw-r--r--kstars/kstars/indi/webcam/vcvt.h73
-rw-r--r--kstars/kstars/indi/webcam/videodev.h346
-rw-r--r--kstars/kstars/indi/webcam/videodev2.h903
205 files changed, 68116 insertions, 0 deletions
diff --git a/kstars/kstars/indi/INDI.dtd b/kstars/kstars/indi/INDI.dtd
new file mode 100644
index 00000000..73d6914a
--- /dev/null
+++ b/kstars/kstars/indi/INDI.dtd
@@ -0,0 +1,128 @@
+<!ENTITY % propState "(Idle|Ok|Busy|Alert)" >
+<!ENTITY % propType "(textField|numericField|oneOfMany|anyOfMany|lights)" >
+<!ENTITY % propValue "(text|number|switch+|light+)" >
+<!ENTITY % switchState "(Off|On)" >
+<!ENTITY % lightState "(Idle|Ok|Busy|Alert)" >
+<!ENTITY % labelValue "(#PCDATA)" >
+<!ENTITY % textValue "(#PCDATA)" >
+<!ENTITY % numberValue "(#PCDATA)" >
+<!ENTITY % message "(#PCDATA)" >
+
+
+<!ENTITY % clientCmds "(getProperties|setValue|getCurValue|getTarValue|message)" >
+<!ELEMENT INDICTest ((%clientCmds;)*) >
+
+<!ELEMENT getProperties EMPTY>
+<!ATTLIST getProperties
+ version CDATA #REQUIRED
+>
+
+<!ELEMENT setValue (%propValue;) >
+<!ATTLIST setValue
+ device CDATA #REQUIRED
+ name CDATA #REQUIRED
+>
+
+<!ELEMENT getCurValue EMPTY>
+<!ATTLIST getCurValue
+ device CDATA #IMPLIED
+ name CDATA #IMPLIED
+>
+
+<!ELEMENT getTarValue EMPTY>
+<!ATTLIST getTarValue
+ device CDATA #IMPLIED
+ name CDATA #IMPLIED
+>
+
+<!ELEMENT message (msg*) >
+
+
+<!ENTITY % serverCmds "(defProperty|curValue|tarValue|delProperty|message)" >
+<!ELEMENT INDISTest ((%serverCmds;)*) >
+
+<!ELEMENT defProperty (%propType;, initCurValue?, initTarValue?, msg*) >
+<!ATTLIST defProperty
+ device CDATA #REQUIRED
+ name CDATA #REQUIRED
+ timeout CDATA "0"
+ state %lightState; #REQUIRED
+>
+
+<!ELEMENT initCurValue (%propValue;) >
+<!ELEMENT initTarValue (%propValue;) >
+
+<!ELEMENT textField EMPTY >
+<!ATTLIST textField
+ perm (ro|wo|rw) #REQUIRED
+ prompt CDATA #REQUIRED
+>
+
+<!ELEMENT numericField (min?, max?, step?) >
+<!ATTLIST numericField
+ perm (ro|wo|rw) #REQUIRED
+ prompt CDATA #REQUIRED
+>
+<!ELEMENT min %numberValue; >
+<!ELEMENT max %numberValue; >
+<!ELEMENT step %numberValue; >
+
+<!ELEMENT oneOfMany EMPTY>
+<!ATTLIST oneOfMany
+ perm (ro|wo) #REQUIRED
+ prompt CDATA #REQUIRED
+>
+
+<!ELEMENT anyOfMany EMPTY>
+<!ATTLIST anyOfMany
+ perm (ro|wo) #REQUIRED
+ prompt CDATA #REQUIRED
+>
+
+<!ELEMENT lights EMPTY>
+<!ATTLIST lights
+ prompt CDATA #REQUIRED
+>
+
+<!ELEMENT text %textValue; >
+
+<!ELEMENT number %numberValue; >
+
+<!ELEMENT switch %labelValue; >
+<!ATTLIST switch
+ state %switchState; #REQUIRED
+>
+
+<!ELEMENT light %labelValue; >
+<!ATTLIST light
+ state %lightState; #REQUIRED
+>
+
+<!ELEMENT msg %message; >
+<!ATTLIST msg
+ time CDATA #IMPLIED
+>
+
+<!ELEMENT curValue (%propValue;, msg*) >
+<!ATTLIST curValue
+ device CDATA #REQUIRED
+ name CDATA #REQUIRED
+ timeout CDATA #IMPLIED
+ state %lightState; #REQUIRED
+>
+
+
+<!ELEMENT tarValue (%propValue;, msg*) >
+<!ATTLIST tarValue
+ device CDATA #REQUIRED
+ name CDATA #REQUIRED
+ timeout CDATA #IMPLIED
+ state %lightState; #REQUIRED
+>
+
+<!ELEMENT delProperty (msg*) >
+<!ATTLIST delProperty
+ device CDATA #REQUIRED
+ name CDATA #IMPLIED
+>
+
diff --git a/kstars/kstars/indi/LICENSE b/kstars/kstars/indi/LICENSE
new file mode 100644
index 00000000..ae23fcfd
--- /dev/null
+++ b/kstars/kstars/indi/LICENSE
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/kstars/kstars/indi/Makefile.am b/kstars/kstars/indi/Makefile.am
new file mode 100644
index 00000000..29aa23a6
--- /dev/null
+++ b/kstars/kstars/indi/Makefile.am
@@ -0,0 +1,82 @@
+appdatadir = $(kde_datadir)/kstars
+appdata_DATA = drivers.xml apogee_caminfo.xml
+
+
+AM_CPPFLAGS = -DTOP_DATADIR=\"$(appdatadir)\"
+
+if LINUX
+bin_add = apogee_ppi sbigccd v4ldriver v4lphilips meade_lpi
+endif
+
+bin_PROGRAMS = indiserver lx200basic lx200generic celestrongps apmount fliccd fliwheel temma skycommander $(bin_add)
+
+liblilxml_a_SOURCES = lilxml.c
+libindicom_a_SOURCES = indicom.c fitsrw.c base64.c
+
+noinst_LIBRARIES = liblilxml.a libindicom.a
+
+indiserver_SOURCES = indiserver.c fq.c
+indiserver_LDADD = liblilxml.a ${LIBPTHREAD} ${USE_THREADS} $(LIBSOCKET)
+
+lx200generic_SOURCES = indidrivermain.c base64.c eventloop.c lx200driver.c lx200autostar.cpp lx200_16.cpp lx200gps.cpp lx200generic.cpp lx200classic.cpp
+lx200generic_LDADD = liblilxml.a libindicom.a -lm
+
+lx200basic_SOURCES = indidrivermain.c base64.c eventloop.c lx200driver.c lx200basic.cpp
+lx200basic_LDADD = liblilxml.a libindicom.a
+
+celestrongps_SOURCES = indidrivermain.c base64.c eventloop.c celestronprotocol.c celestrongps.cpp
+celestrongps_LDADD = liblilxml.a libindicom.a -lm
+
+apmount_SOURCES = indidrivermain.c base64.c eventloop.c lx200driver.c apmount.cpp
+apmount_LDADD = liblilxml.a libindicom.a
+
+fliccd_SOURCES = eventloop.c base64.c fli_ccd.c indidrivermain.c
+fliccd_LDADD = fli/libfli.la libindicom.a liblilxml.a -lm -lz $(LIBSOCKET)
+
+fliwheel_SOURCES = eventloop.c base64.c fli_wheel.c indidrivermain.c
+fliwheel_LDADD = fli/libfli.la libindicom.a liblilxml.a -lm
+
+v4ldriver_SOURCES = eventloop.c base64.c indidrivermain.c v4ldriver.cpp indi_v4l.cpp
+v4ldriver_LDADD = libindicom.a liblilxml.a webcam/libwebcam.la -lm -lz
+
+v4lphilips_SOURCES = eventloop.c base64.c indidrivermain.c v4ldriver.cpp v4lphilips.cpp indi_philips.cpp
+v4lphilips_LDADD = libindicom.a liblilxml.a webcam/libwebcam.la -lm -lz
+
+meade_lpi_SOURCES = eventloop.c base64.c indidrivermain.c v4ldriver.cpp indi_lpi.cpp
+meade_lpi_LDADD = libindicom.a liblilxml.a webcam/libwebcam.la -lz
+
+temma_SOURCES = indidrivermain.c base64.c eventloop.c temmadriver.c
+temma_LDADD = liblilxml.a libindicom.a -lm
+
+skycommander_SOURCES = indidrivermain.c base64.c eventloop.c lx200driver.c skycommander.c
+skycommander_LDADD = liblilxml.a libindicom.a -lm
+
+apogee_ppi_SOURCES = apogee_ppi.cpp base64.c eventloop.c indidrivermain.c
+apogee_ppi_LDADD = libindicom.a liblilxml.a apogee/libapogee_PPI.la -lz
+
+sbigccd_SOURCES = sbigccd.cpp base64.c eventloop.c indidrivermain.c
+sbigccd_LDADD = libindicom.a liblilxml.a -lz
+
+install-exec-hook:
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ rm -f $(DESTDIR)$(bindir)/lx200classic
+ $(LN_S) lx200generic $(DESTDIR)$(bindir)/lx200classic
+ rm -f $(DESTDIR)$(bindir)/lx200autostar
+ $(LN_S) lx200generic $(DESTDIR)$(bindir)/lx200autostar
+ rm -f $(DESTDIR)$(bindir)/lx200_16
+ $(LN_S) lx200generic $(DESTDIR)$(bindir)/lx200_16
+ rm -f $(DESTDIR)$(bindir)/lx200gps
+ $(LN_S) lx200generic $(DESTDIR)$(bindir)/lx200gps
+
+uninstall-local:
+ rm $(DESTDIR)$(bindir)/lx200autostar $(DESTDIR)$(bindir)/lx200_16 $(DESTDIR)$(bindir)/lx200gps
+
+KDE_OPTIONS = nofinal
+
+if LINUX
+SUBDIRS = fli webcam apogee
+else
+SUBDIRS = fli apogee
+endif
+
+include $(top_srcdir)/admin/Doxyfile.am
diff --git a/kstars/kstars/indi/README b/kstars/kstars/indi/README
new file mode 100644
index 00000000..0ec3e688
--- /dev/null
+++ b/kstars/kstars/indi/README
@@ -0,0 +1,103 @@
+The code here demonstrates the use of INDI, an Instrument-Neutral Device
+Interface protocol. See http://www.clearskyinstitute.com/INDI/INDI.pdf.
+
+Architecture:
+
+ Typical INDI Client / Server / Driver / Device connectivity:
+
+
+ INDI Client 1 ----| |---- INDI Driver A ---- Dev X
+ | |
+ INDI Client 2 ----| |---- INDI Driver B ---- Dev Y
+ | | |
+ ... |--- indiserver ---| |-- Dev Z
+ | |
+ | |
+ INDI Client n ----| |---- INDI Driver C ---- Dev T
+
+
+ Client INET Server UNIX Driver Hardware
+ processes sockets process pipes processes devices
+
+
+
+ Indiserver is the public network access point where one or more INDI Clients
+ may contact one or more INDI Drivers. Indiserver launches each driver
+ process and arranges for it to receive the INDI protocol from Clients on
+ its stdin and expects to find commands destined for Clients on the
+ driver's stdout. Anything arriving from a driver process' stderr is copied
+ to indiserver's stderr.
+
+ Indiserver only provides convenient port, fork and data steering services.
+ If desired, a Client may run and connect to INDI Drivers directly.
+
+Construction:
+
+ An INDI driver typically consists of one .c file, eg, mydriver.c, which
+ #includes indiapi.h to access the reference API declarations. It is
+ compiled then linked with indidrivermain.o, eventloop.o and liblilxml.a to
+ form an INDI process. These supporting files contain the implementation of
+ the INDI Driver API and need not be changed in any way. Note that
+ evenloop.[ch] provide a nice callback facility independent of INDI which
+ may be used in other projects if desired.
+
+ The driver implementation, again in our example mydriver.c, does not
+ contain a main() but is expected to operate as an event-driver program.
+ The driver must implement each ISxxx() function but never call them. The
+ IS() functions are called by the reference implementation main() as messages
+ arrive from Clients. Within each IS function the driver performs the
+ desired tasks then may report back to the Client by calling the IDxxx()
+ functions.
+
+ The reference API provides IE() functions to allow the driver to add its
+ own callback functions if desired. The driver can arrange for functions to
+ be called when reading a file descriptor will not block; when a time
+ interval has expired; or when there is no other client traffic in progress.
+
+ The sample indiserver is a stand alone process that may be used to run one
+ or more INDI-compliant drivers. It takes the names of each driver process
+ to run in its command line args.
+
+ To build indiserver type 'make indiserver';
+ to build all the sample drivers type 'make drivers';
+ to run the sample server with all drivers type 'make run'.
+ Killing indiserver will also kill all the drivers it started.
+
+Secure remote operation:
+
+ Suppose we want to run indiserver and its clients on a remote machine, r,
+ and connect them to our favorite INDI client, XEphem, running on the
+ local machine.
+
+ From the local machine log onto the remote machine, r, by typing:
+
+ ssh2 -L 7624:s:7624 r
+
+ after logging in, run indiserver on the remote machine:
+
+ make run
+
+ Back on the local machine, start XEphem, then open Views -> Sky View ->
+ Telescope -> INDI panel. XEphem will connect to the remote INDI server
+ securely and automatically begin running. Sweet.
+
+Testing:
+
+ A low-level way to test the socket, forking and data steering abilities of
+ indiserver is to use the 'hose' command from the netpipes collection
+ (http://web.purplefrog.com/~thoth/netpipes/netpipes.html):
+
+ 1. start indiserver using UNIX' cat program as the only INDI "device":
+
+ % indiserver cat &
+
+ 2. use hose to connect to the "cat" device driver which just copies back:
+
+ % hose localhost 7624 --slave
+ hello world
+ hello world
+ more stuff
+ more stuff
+
+! For RCS Only -- Do Not Edit
+! @(#) $RCSfile$ $Date$ $Revision$ $Name: $
diff --git a/kstars/kstars/indi/SchedGUI b/kstars/kstars/indi/SchedGUI
new file mode 100644
index 00000000..de99888d
--- /dev/null
+++ b/kstars/kstars/indi/SchedGUI
@@ -0,0 +1,70 @@
+Control
+
+ INDI Server
+
+ Address | | DNS or IP address of INDI server
+ Port | | tcp port of INDI server
+ [] Connect
+
+Observing Request
+
+ Administrative
+
+ [] Name | |
+ [] Email | |
+ [] Project | |
+ [] Priority | | integer, smaller is better
+
+ Constraints
+
+ Sun:
+
+ [] Min sep | | ° from target
+ [] Min down | | ° below horizon
+
+ Moon:
+
+ [] Max phase | | 0..1 (new..full)
+ [] Min sep | | ° from target
+ [] Min down | | ° below horizon
+
+ Timing:
+
+ [] Phase portion of cyclic phenomenon
+ start | | phase reference, ISO 8601
+ period | | total period, days
+ earliest | | acceptable start window, 0..1
+ latest | | acceptable end window, 0..1
+ [] Earliest | | Do not schedule before, ISO 8601
+ [] Latest | | Do not schedule after, ISO 8601
+
+ Conditions:
+
+ [] Max airmass | | max acceptable airmass, 1..99
+
+ Repetitions
+
+ [] Count | | number of total sets, 1..
+ [] Every | | start interval, minutes
+ [] Min gap | | repeat no sooner, minutes
+ [] Same night | | require all on same night, Yes or No
+ [] Tolerance | | acceptable start deviation, minutes
+
+ Create
+
+ Del Device + Param Target value at by secs
+ ---------------------------------------------------------
+ | [] | Roof open | True | < > <x> t= | 0 |
+ | [] | Mount RA | | < > <x> t= | 0 |
+ | [] | Mount Dec | | < > <x> t= | 0 |
+ | [] | OTA Filter | Blue | < > <x> t= | 0 |
+ | [] | Camera temp | -40 | < > <x> t= | -10 |
+ | [] | Camera shutter | Open | <x> < > t= | 0 |
+ | [] | Camera shutter | Closed | <x> < > t= | 10 |
+ | [] | Camera shutter | Open | <x> < > t= | 20 |
+ | [] | Camera shutter | Closed | <x> < > t= | 60 |
+ ---------------------------------------------------------
+
+ [] Preview
+ [] Load | | load existing file name
+ [] Save | | save as file name
diff --git a/kstars/kstars/indi/apmount.cpp b/kstars/kstars/indi/apmount.cpp
new file mode 100644
index 00000000..d1c05b66
--- /dev/null
+++ b/kstars/kstars/indi/apmount.cpp
@@ -0,0 +1,1660 @@
+#if 0
+ Astro-Physics driver
+ Copyright (C) 2005 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "indicom.h"
+#include "lx200driver.h"
+#include "apmount.h"
+
+/*
+** Return the timezone offset in hours (as a double, so fractional
+** hours are possible, for instance in Newfoundland). Also sets
+** daylight on non-Linux systems to record whether DST is in effect.
+*/
+
+
+#if !(TIMEZONE_IS_INT)
+static int daylight = 0;
+#endif
+
+static inline double timezoneOffset()
+{
+/*
+** In Linux, there's a timezone variable that holds the timezone offset;
+** Otherwise, we need to make a little detour. The directions of the offset
+** are different: CET is -3600 in Linux and +3600 elsewhere.
+*/
+#if TIMEZONE_IS_INT
+ return timezone / (60 * 60);
+#else
+ time_t now;
+ struct tm *tm;
+ now = time(NULL);
+ tm = localtime(&now);
+ daylight = tm->tm_isdst;
+ return -(tm->tm_gmtoff) / (60 * 60);
+#endif
+}
+
+APMount *telescope = NULL;
+int MaxReticleFlashRate = 3;
+extern char* me;
+
+/* There is _one_ binary for all LX200 drivers, but each binary is renamed
+** to its device name (i.e. lx200gps, lx200_16..etc). The main function will
+** fetch from std args the binary name and ISInit will create the apporpiate
+** device afterwards. If the binary name does not match any known devices,
+** we simply create a generic device
+*/
+
+
+#define COMM_GROUP "Communication"
+#define BASIC_GROUP "Main Control"
+#define MOVE_GROUP "Movement Control"
+#define FOCUS_GROUP "Focus Control"
+
+#define mydev "Astro-Physics"
+#define currentRA EqN[0].value
+#define currentDEC EqN[1].value
+
+#define RA_THRESHOLD 0.01
+#define DEC_THRESHOLD 0.05
+#define LX200_SLEW 0
+#define LX200_TRACK 1
+#define LX200_SYNC 2
+#define LX200_PARK 3
+
+static void ISPoll(void *);
+static void retryConnection(void *);
+
+/*INDI controls */
+
+
+/* send client definitions of all properties */
+void ISInit()
+{
+ static int isInit=0;
+
+ if (isInit)
+ return;
+
+ isInit = 1;
+
+ telescope = new APMount();
+ IEAddTimer (POLLMS, ISPoll, NULL);
+}
+
+void ISGetProperties (const char *dev)
+{
+ ISInit();
+ telescope->ISGetProperties(dev);
+}
+
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ ISInit();
+ telescope->ISNewSwitch(dev, name, states, names, n);
+}
+
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+ ISInit();
+ telescope->ISNewText(dev, name, texts, names, n);
+}
+
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ ISInit();
+ telescope->ISNewNumber(dev, name, values, names, n);
+}
+
+void ISPoll (void */*p*/)
+{
+ telescope->ISPoll();
+ IEAddTimer (POLLMS, ISPoll, NULL);
+}
+
+void ISNewBLOB (const char */*dev*/, const char */*name*/, int */*sizes[]*/, char **/*blobs[]*/, char **/*formats[]*/, char **/*names[]*/, int /*n*/)
+{}
+
+/**************************************************
+*** AP Mount
+***************************************************/
+
+APMount::APMount()
+{
+ struct tm *utp;
+ time_t t;
+ time (&t);
+ utp = gmtime (&t);
+
+ initProperties();
+
+ currentSiteNum = 1;
+ trackingMode = 2;
+ lastSet = -1;
+ fault = false;
+ simulation = false;
+ targetRA = 0;
+ targetDEC = 0;
+ currentSet = 0;
+ UTCOffset = 0;
+ lastMove[0] = lastMove[1] = lastMove[2] = lastMove[3] = 0;
+
+ localTM = new tm;
+
+ utp->tm_mon += 1;
+ utp->tm_year += 1900;
+ JD = UTtoJD(utp);
+
+ IDLog("Julian Day is %g\n", JD);
+ IDLog("Initilizing from Astro-Physics device...\n");
+ IDLog("Driver Version: 2005-05-26\n");
+
+ //enableSimulation(true);
+}
+
+void APMount::initProperties()
+{
+
+ fillSwitch(&AlignmentS[0], "Polar", "", ISS_ON);
+ fillSwitch(&AlignmentS[1], "AltAz", "", ISS_OFF);
+ fillSwitchVector(&AlignmentSP, AlignmentS, NARRAY(AlignmentS), mydev, "Alignment", "", COMM_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ fillSwitch(&PowerS[0], "CONNECT", "Connect", ISS_OFF);
+ fillSwitch(&PowerS[1], "DISCONNECT", "Disconnect", ISS_ON);
+ fillSwitchVector(&PowerSP, PowerS, NARRAY(PowerS), mydev, "CONNECTION", "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
+
+ fillSwitch(&OnCoordSetS[0], "SLEW", "Slew", ISS_ON);
+ fillSwitch(&OnCoordSetS[1], "TRACK", "Track", ISS_OFF);
+ fillSwitch(&OnCoordSetS[2], "SYNC", "Sync", ISS_OFF);
+ fillSwitchVector(&OnCoordSetSP, OnCoordSetS, NARRAY(OnCoordSetS), mydev, "ON_COORD_SET", "On Set", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ fillSwitch(&TrackModeS[0], "Lunar", "", ISS_OFF);
+ fillSwitch(&TrackModeS[1], "Solar", "", ISS_OFF);
+ fillSwitch(&TrackModeS[2], "Sideral", "", ISS_ON);
+ fillSwitch(&TrackModeS[3], "Zero", "", ISS_OFF);
+ fillSwitchVector(&TrackModeSP, TrackModeS, NARRAY(TrackModeS), mydev, "Tracking Mode", "", MOVE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ fillSwitch(&AbortSlewS[0], "ABORT", "Abort", ISS_OFF);
+ fillSwitchVector(&AbortSlewSP, AbortSlewS, NARRAY(AbortSlewS), mydev, "ABORT_MOTION", "Abort Slew/Track", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ fillSwitch(&ParkS[0], "PARK", "Park", ISS_OFF);
+ fillSwitch(&ParkS[1], "UNPARK", "Unpark", ISS_OFF);
+ fillSwitchVector(&ParkSP, ParkS, NARRAY(ParkS), mydev, "PARK", "Park Scope", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ fillSwitch(&MovementS[0], "N", "North", ISS_OFF);
+ fillSwitch(&MovementS[1], "W", "West", ISS_OFF);
+ fillSwitch(&MovementS[2], "E", "East", ISS_OFF);
+ fillSwitch(&MovementS[3], "S", "South", ISS_OFF);
+ fillSwitchVector(&MovementSP, MovementS, NARRAY(MovementS), mydev, "MOVEMENT", "Move toward", MOVE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ fillSwitch(&FocusMotionS[0], "IN", "Focus in", ISS_OFF);
+ fillSwitch(&FocusMotionS[1], "OUT", "Focus out", ISS_OFF);
+ fillSwitchVector(&FocusMotionSP, FocusMotionS, NARRAY(FocusMotionS), mydev, "FOCUS_MOTION", "Motion", FOCUS_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ fillText(&PortT[0], "PORT", "Port", "/dev/ttyS0");
+ fillTextVector(&PortTP, PortT, NARRAY(PortT), mydev, "DEVICE_PORT", "Ports", COMM_GROUP, IP_RW, 0, IPS_IDLE);
+
+ fillText(&UTCT[0], "UTC", "", "YYYY-MM-DDTHH:MM:SS");
+ fillTextVector(&TimeTP, UTCT, NARRAY(UTCT), mydev, "TIME", "UTC Time", COMM_GROUP, IP_RW, 0, IPS_IDLE);
+
+ fillText(&ObjectT[0], "OBJECT_NAME", "Name", "--");
+ fillTextVector(&ObjectTP, ObjectT, NARRAY(ObjectT), mydev, "OBJECT_INFO", "Object", BASIC_GROUP, IP_RW, 0, IPS_IDLE);
+
+ fillNumber(&EqN[0], "RA", "RA H:M:S", "%10.6m", 0., 24., 0., 0.);
+ fillNumber(&EqN[1], "DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0.);
+ fillNumberVector(&EqNP, EqN, NARRAY(EqN), mydev, "EQUATORIAL_EOD_COORD" , "Equatorial JNow", BASIC_GROUP, IP_RW, 0, IPS_IDLE);
+
+ fillNumber(&GeoN[0], "LAT", "Lat. D:M:S +N", "%10.6m", -90., 90., 0., 0.);
+ fillNumber(&GeoN[1], "LONG", "Long. D:M:S +E", "%10.6m", 0., 360., 0., 0.);
+ fillNumberVector(&GeoNP, GeoN, NARRAY(GeoN), mydev, "GEOGRAPHIC_COORD", "Geographic Location", COMM_GROUP, IP_RW, 0, IPS_IDLE);
+
+ fillNumber(&FocusTimerN[0], "TIMEOUT", "Timeout (s)", "%10.6m", 0., 120., 1., 0.);
+ fillNumberVector(&FocusTimerNP, FocusTimerN, NARRAY(FocusTimerN), mydev, "FOCUS_TIMEOUT", "Focus Timer", FOCUS_GROUP, IP_RW, 0, IPS_IDLE);
+
+ fillNumber(&SDTimeN[0], "LST", "Sidereal time", "%10.6m" , 0.,24.,0.,0.);
+ fillNumberVector(&SDTimeNP, SDTimeN, NARRAY(SDTimeN), mydev, "SDTIME", "Sidereal Time", COMM_GROUP, IP_RW, 0, IPS_IDLE);
+
+ fillNumber(&HorN[0], "ALT", "Alt D:M:S", "%10.6m", -90., 90., 0., 0.);
+ fillNumber(&HorN[1], "AZ", "Az D:M:S", "%10.6m", 0., 360., 0., 0.);
+ fillNumberVector(&HorNP, HorN, NARRAY(HorN), mydev, "HORIZONTAL_COORD", "Horizontal Coords", BASIC_GROUP, IP_RW, 0, IPS_IDLE);
+
+ fillNumber(&FocusSpeedN[0], "SPEED", "Speed", "%0.f", 0., 3., 1., 0.);
+ fillNumberVector(&FocusSpeedNP, FocusSpeedN, NARRAY(FocusSpeedN), mydev, "FOCUS_SPEED", "Speed", FOCUS_GROUP, IP_RW, 0, IPS_IDLE);
+
+
+}
+
+void APMount::ISGetProperties(const char *dev)
+{
+
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ // COMM_GROUP
+ IDDefSwitch(&PowerSP, NULL);
+ IDDefText(&PortTP, NULL);
+ IDDefSwitch(&AlignmentSP, NULL);
+ IDDefText(&TimeTP, NULL);
+ IDDefNumber(&SDTimeNP, NULL);
+ IDDefNumber(&GeoNP, NULL);
+
+ // MAIN CONTROL
+ IDDefText(&ObjectTP, NULL);
+ IDDefNumber(&EqNP, NULL);
+ //IDDefNumber(&HorNP, NULL);
+ IDDefSwitch(&OnCoordSetSP, NULL);
+ IDDefSwitch(&AbortSlewSP, NULL);
+ IDDefSwitch(&ParkSP, NULL);
+
+ // MOVEMENT CONTROL
+ IDDefSwitch(&TrackModeSP, NULL);
+ IDDefSwitch(&MovementSP, NULL);
+
+ // FOCUS CONTROL
+ IDDefNumber(&FocusSpeedNP, NULL);
+ IDDefSwitch(&FocusMotionSP, NULL);
+ IDDefNumber(&FocusTimerNP, NULL);
+
+ /* Send the basic data to the new client if the previous client(s) are already connected. */
+ if (PowerSP.s == IPS_OK)
+ getBasicData();
+
+}
+
+void APMount::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int /*n*/)
+{
+ int err;
+ struct tm *ltp = new tm;
+ struct tm utm;
+ time_t ltime;
+ time (&ltime);
+ localtime_r (&ltime, ltp);
+ IText *tp;
+
+ // ignore if not ours
+ if (strcmp (dev, mydev))
+ return;
+
+ // Port name
+ if (!strcmp(name, PortTP.name) )
+ {
+ PortTP.s = IPS_OK;
+ tp = IUFindText( &PortTP, names[0] );
+ if (!tp)
+ return;
+
+ IUSaveText(tp, texts[0]);
+ IDSetText (&PortTP, NULL);
+ return;
+ }
+
+ // Time
+ if (!strcmp (name, TimeTP.name))
+ {
+ if (checkPower(&TimeTP))
+ return;
+
+ if (extractISOTime(texts[0], &utm) < 0)
+ {
+ TimeTP.s = IPS_IDLE;
+ IDSetText(&TimeTP , "Time invalid");
+ return;
+ }
+ ltp->tm_mon += 1;
+ ltp->tm_year += 1900;
+
+ tzset();
+
+ UTCOffset = timezoneOffset();
+
+ IDLog("local time is %02d:%02d:%02d\nUTCOffset: %g\n", ltp->tm_hour, ltp->tm_min, ltp->tm_sec, UTCOffset);
+
+ getSDTime(&SDTimeN[0].value);
+ IDSetNumber(&SDTimeNP, NULL);
+
+ if ( ( err = setUTCOffset(UTCOffset) < 0) )
+ {
+ TimeTP.s = IPS_ALERT;
+ IDSetText( &TimeTP , "Setting UTC Offset failed.");
+ return;
+ }
+
+ if ( ( err = setLocalTime(ltp->tm_hour, ltp->tm_min, ltp->tm_sec) < 0) )
+ {
+ handleError(&TimeTP, err, "Setting local time");
+ return;
+ }
+
+ tp = IUFindText(&TimeTP, names[0]);
+ if (!tp)
+ return;
+ IUSaveText(tp, texts[0]);
+ TimeTP.s = IPS_OK;
+
+ // update JD
+ JD = UTtoJD(&utm);
+
+ IDLog("New JD is %f\n", (float) JD);
+
+ if ((localTM->tm_mday == ltp->tm_mday ) && (localTM->tm_mon == ltp->tm_mon) &&
+ (localTM->tm_year == ltp->tm_year))
+ {
+ IDSetText(&TimeTP , "Time updated to %s", texts[0]);
+ return;
+ }
+
+ delete (localTM);
+ localTM = ltp;
+
+ if ( ( err = setCalenderDate(ltp->tm_mday, ltp->tm_mon, ltp->tm_year) < 0) )
+ {
+ handleError(&TimeTP, err, "Setting local date.");
+ return;
+ }
+
+ IDSetText(&TimeTP , "Date changed, updating planetary data...");
+ }
+
+ if (!strcmp (name, ObjectTP.name))
+ {
+ if (checkPower(&ObjectTP))
+ return;
+
+ IUSaveText(&ObjectT[0], texts[0]);
+ ObjectTP.s = IPS_OK;
+ IDSetText(&ObjectTP, NULL);
+ return;
+ }
+
+}
+
+
+void APMount::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ int h =0, m =0, s=0, err;
+ double newRA =0, newDEC =0;
+
+ // ignore if not ours //
+ if (strcmp (dev, mydev))
+ return;
+
+ if (!strcmp (name, EqNP.name))
+ {
+ int i=0, nset=0;
+
+ if (checkPower(&EqNP))
+ return;
+
+ for (nset = i = 0; i < n; i++)
+ {
+ INumber *eqp = IUFindNumber (&EqNP, names[i]);
+ if (eqp == &EqN[0])
+ {
+ newRA = values[i];
+ nset += newRA >= 0 && newRA <= 24.0;
+ } else if (eqp == &EqN[1])
+ {
+ newDEC = values[i];
+ nset += newDEC >= -90.0 && newDEC <= 90.0;
+ }
+ }
+
+ if (nset == 2)
+ {
+ char RAStr[32], DecStr[32];
+
+ fs_sexa(RAStr, newRA, 2, 3600);
+ fs_sexa(DecStr, newDEC, 2, 3600);
+
+ IDLog("We received JNow RA %g - DEC %g\n", newRA, newDEC);
+ IDLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);
+
+ if ( (err = setObjectRA(newRA)) < 0 || ( err = setObjectDEC(newDEC)) < 0)
+ {
+ handleError(&EqNP, err, "Setting RA/DEC");
+ return;
+ }
+
+ targetRA = newRA;
+ targetDEC = newDEC;
+
+ if (MovementSP.s == IPS_BUSY)
+ {
+ for (int i=0; i < 4; i++)
+ {
+ lastMove[i] = 0;
+ MovementS[i].s = ISS_OFF;
+ }
+
+ MovementSP.s = IPS_IDLE;
+ IDSetSwitch(&MovementSP, NULL);
+ }
+
+ if (handleCoordSet())
+ {
+ EqNP.s = IPS_IDLE;
+ IDSetNumber(&EqNP, NULL);
+
+ }
+ } // end nset
+ else
+ {
+ EqNP.s = IPS_IDLE;
+ IDSetNumber(&EqNP, "RA or Dec missing or invalid");
+ }
+
+ return;
+ } /* end EqNP */
+
+ // Sideral Time
+ if ( !strcmp (name, SDTimeNP.name) )
+ {
+
+ if (checkPower(&SDTimeNP))
+ return;
+
+ if (values[0] < 0.0 || values[0] > 24.0)
+ {
+ SDTimeNP.s = IPS_IDLE;
+ IDSetNumber(&SDTimeNP , "Time invalid");
+ return;
+ }
+
+ getSexComponents(values[0], &h, &m, &s);
+ IDLog("Time is %02d:%02d:%02d\n", h, m, s);
+
+ if ( ( err = setSDTime(h, m, s) < 0) )
+ {
+ handleError(&SDTimeNP, err, "Setting siderial time");
+ return;
+ }
+
+ SDTimeNP.np[0].value = values[0];
+ SDTimeNP.s = IPS_OK;
+
+ IDSetNumber(&SDTimeNP , "Sidereal time updated to %02d:%02d:%02d", h, m, s);
+
+ return;
+ }
+
+ // Geographical location
+ if (!strcmp (name, GeoNP.name))
+ {
+ // new geographic coords
+ double newLong = 0, newLat = 0;
+ int i, nset;
+ char msg[128];
+
+ if (checkPower(&GeoNP))
+ return;
+
+ for (nset = i = 0; i < n; i++)
+ {
+ INumber *geop = IUFindNumber (&GeoNP, names[i]);
+ if (geop == &GeoN[0])
+ {
+ newLat = values[i];
+ nset += newLat >= -90.0 && newLat <= 90.0;
+ } else if (geop == &GeoN[1])
+ {
+ newLong = values[i];
+ nset += newLong >= 0.0 && newLong < 360.0;
+ }
+ }
+
+ if (nset == 2)
+ {
+ char l[32], L[32];
+ GeoNP.s = IPS_OK;
+ fs_sexa (l, newLat, 3, 3600);
+ fs_sexa (L, newLong, 4, 3600);
+
+ if ( ( err = setSiteLongitude(360.0 - newLong) < 0) )
+ {
+ handleError(&GeoNP, err, "Setting site coordinates");
+ return;
+ }
+
+ setSiteLatitude(newLat);
+ GeoNP.np[0].value = newLat;
+ GeoNP.np[1].value = newLong;
+ snprintf (msg, sizeof(msg), "Site location updated to Lat %.32s - Long %.32s", l, L);
+ } else
+ {
+ GeoNP.s = IPS_IDLE;
+ strcpy(msg, "Lat or Long missing or invalid");
+ }
+ IDSetNumber (&GeoNP, "%s", msg);
+ return;
+ }
+
+ // Focus TImer
+ if (!strcmp(name, FocusTimerNP.name))
+ {
+ if (checkPower(&FocusTimerNP))
+ return;
+
+ // Don't update if busy
+ if (FocusTimerNP.s == IPS_BUSY)
+ return;
+
+ IUUpdateNumbers(&FocusTimerNP, values, names, n);
+
+ FocusTimerNP.s = IPS_OK;
+
+ IDSetNumber(&FocusTimerNP, NULL);
+ IDLog("Setting focus timer to %g\n", FocusTimerN[0].value);
+
+ return;
+
+ }
+
+ // Focus speed
+ if (!strcmp (name, FocusSpeedNP.name))
+ {
+ if (checkPower(&FocusSpeedNP))
+ return;
+
+ if (IUUpdateNumbers(&FocusSpeedNP, values, names, n) < 0)
+ return;
+
+ /* disable timer and motion */
+ if (FocusSpeedN[0].value == 0)
+ {
+ FocusMotionSP.s = IPS_IDLE;
+ FocusTimerNP.s = IPS_IDLE;
+ IDSetSwitch(&FocusMotionSP, NULL);
+ IDSetNumber(&FocusTimerNP, NULL);
+ }
+
+ setFocuserSpeedMode( ( (int) FocusSpeedN[0].value));
+ FocusSpeedNP.s = IPS_OK;
+ IDSetNumber(&FocusSpeedNP, NULL);
+ return;
+ }
+
+}
+
+void APMount::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ int index;
+ int err;
+ char combinedDir[64];
+ ISwitch *swp;
+
+ // ignore if not ours //
+ if (strcmp (mydev, dev))
+ return;
+
+ // Connection
+ if (!strcmp (name, PowerSP.name))
+ {
+ IUResetSwitches(&PowerSP);
+ IUUpdateSwitches(&PowerSP, states, names, n);
+ powerTelescope();
+ return;
+ }
+
+ // Coord set
+ if (!strcmp(name, OnCoordSetSP.name))
+ {
+ if (checkPower(&OnCoordSetSP))
+ return;
+
+ IUResetSwitches(&OnCoordSetSP);
+ IUUpdateSwitches(&OnCoordSetSP, states, names, n);
+ currentSet = getOnSwitch(&OnCoordSetSP);
+ OnCoordSetSP.s = IPS_OK;
+ IDSetSwitch(&OnCoordSetSP, NULL);
+ }
+
+ // Parking
+ if (!strcmp(name, ParkSP.name))
+ {
+ if (checkPower(&ParkSP))
+ return;
+
+ IUResetSwitches(&ParkSP);
+ IUUpdateSwitches(&ParkSP, states, names, n);
+ index = getOnSwitch(&ParkSP);
+
+ // Park Command
+ if (index == 0)
+ APPark();
+ else
+ // Unpark
+ {
+ char **tmtexts = (char **) malloc(1);
+ char **tmtp = (char **) malloc(1);
+ tmtexts[0] = (char *) malloc (32);
+ tmtp[0] = (char *) malloc (32);
+
+ strcpy(tmtexts[0], timestamp());
+ strcpy(tmtp[0], "UTC");
+
+ // Update date and time before unparking
+ ISNewText(mydev, "TIME", tmtexts, tmtp, 1);
+ APUnpark();
+
+ free (tmtexts);
+ free (tmtp);
+ }
+
+ ParkSP.s = IPS_OK;
+ IDSetSwitch(&ParkSP, (index == 0) ? "Parking..." : "Unparking...");
+ return;
+ }
+
+ // Abort Slew
+ if (!strcmp (name, AbortSlewSP.name))
+ {
+ if (checkPower(&AbortSlewSP))
+ {
+ AbortSlewSP.s = IPS_IDLE;
+ IDSetSwitch(&AbortSlewSP, NULL);
+ return;
+ }
+
+ IUResetSwitches(&AbortSlewSP);
+ abortSlew();
+
+ if (EqNP.s == IPS_BUSY)
+ {
+ AbortSlewSP.s = IPS_OK;
+ EqNP.s = IPS_IDLE;
+ IDSetSwitch(&AbortSlewSP, "Slew aborted.");
+ IDSetNumber(&EqNP, NULL);
+ }
+ else if (MovementSP.s == IPS_BUSY)
+ {
+
+ for (int i=0; i < 4; i++)
+ lastMove[i] = 0;
+
+ MovementSP.s = IPS_IDLE;
+ AbortSlewSP.s = IPS_OK;
+ EqNP.s = IPS_IDLE;
+ IUResetSwitches(&MovementSP);
+ IUResetSwitches(&AbortSlewSP);
+ IDSetSwitch(&AbortSlewSP, "Slew aborted.");
+ IDSetSwitch(&MovementSP, NULL);
+ IDSetNumber(&EqNP, NULL);
+ }
+ else
+ {
+ IUResetSwitches(&MovementSP);
+ AbortSlewSP.s = IPS_OK;
+ IDSetSwitch(&AbortSlewSP, NULL);
+ }
+
+ return;
+ }
+
+ // Alignment
+ if (!strcmp (name, AlignmentSP.name))
+ {
+ if (checkPower(&AlignmentSP))
+ return;
+
+ IUResetSwitches(&AlignmentSP);
+ IUUpdateSwitches(&AlignmentSP, states, names, n);
+ index = getOnSwitch(&AlignmentSP);
+
+ if ( ( err = setAlignmentMode(index) < 0) )
+ {
+ handleError(&AlignmentSP, err, "Setting alignment");
+ return;
+ }
+
+ AlignmentSP.s = IPS_OK;
+ IDSetSwitch (&AlignmentSP, NULL);
+ return;
+
+ }
+
+ // Focus Motion
+ if (!strcmp (name, FocusMotionSP.name))
+ {
+ if (checkPower(&FocusMotionSP))
+ return;
+
+ IUResetSwitches(&FocusMotionSP);
+
+ // If speed is "halt"
+ if (FocusSpeedN[0].value == 0)
+ {
+ FocusMotionSP.s = IPS_IDLE;
+ IDSetSwitch(&FocusMotionSP, NULL);
+ return;
+ }
+
+ IUUpdateSwitches(&FocusMotionSP, states, names, n);
+ index = getOnSwitch(&FocusMotionSP);
+
+ if ( ( err = setFocuserMotion(index) < 0) )
+ {
+ handleError(&FocusMotionSP, err, "Setting focuser speed");
+ return;
+ }
+
+ FocusMotionSP.s = IPS_BUSY;
+
+ // with a timer
+ if (FocusTimerN[0].value > 0)
+ FocusTimerNP.s = IPS_BUSY;
+
+ IDSetSwitch(&FocusMotionSP, NULL);
+ return;
+ }
+
+ // Movement
+ if (!strcmp (name, MovementSP.name))
+ {
+ if (checkPower(&MovementSP))
+ return;
+
+ index = -1;
+ IUUpdateSwitches(&MovementSP, states, names, n);
+ swp = IUFindSwitch(&MovementSP, names[0]);
+
+ if (!swp)
+ {
+ abortSlew();
+ IUResetSwitches(&MovementSP);
+ MovementSP.s = IPS_IDLE;
+ IDSetSwitch(&MovementSP, NULL);
+ }
+
+ if (swp == &MovementS[0]) index = 0;
+ else if (swp == &MovementS[1]) index = 1;
+ else if (swp == &MovementS[2]) index = 2;
+ else index = 3;
+
+ lastMove[index] = lastMove[index] == 0 ? 1 : 0;
+ if (lastMove[index] == 0)
+ MovementS[index].s = ISS_OFF;
+
+ // North/South movement is illegal
+ if (lastMove[LX200_NORTH] && lastMove[LX200_SOUTH])
+ {
+ abortSlew();
+ for (int i=0; i < 4; i++)
+ lastMove[i] = 0;
+
+ IUResetSwitches(&MovementSP);
+ MovementSP.s = IPS_IDLE;
+ IDSetSwitch(&MovementSP, "Slew aborted.");
+ return;
+ }
+
+ // East/West movement is illegal
+ if (lastMove[LX200_EAST] && lastMove[LX200_WEST])
+ {
+ abortSlew();
+ for (int i=0; i < 4; i++)
+ lastMove[i] = 0;
+
+ IUResetSwitches(&MovementSP);
+ MovementSP.s = IPS_IDLE;
+ IDSetSwitch(&MovementSP, "Slew aborted.");
+ return;
+ }
+
+ IDLog("We have switch %d \n ", index);
+ IDLog("NORTH: %d -- WEST: %d -- EAST: %d -- SOUTH %d\n", lastMove[0], lastMove[1], lastMove[2], lastMove[3]);
+
+ if (lastMove[index] == 1)
+ {
+ IDLog("issuing a move command\n");
+ if ( ( err = MoveTo(index) < 0) )
+ {
+ handleError(&MovementSP, err, "Setting motion direction");
+ return;
+ }
+ }
+ else
+ HaltMovement(index);
+
+ if (!lastMove[0] && !lastMove[1] && !lastMove[2] && !lastMove[3])
+ MovementSP.s = IPS_IDLE;
+
+ if (lastMove[index] == 0)
+ IDSetSwitch(&MovementSP, "Moving toward %s aborted.", Direction[index]);
+ else
+ {
+ MovementSP.s = IPS_BUSY;
+ if (lastMove[LX200_NORTH] && lastMove[LX200_WEST])
+ strcpy(combinedDir, "North West");
+ else if (lastMove[LX200_NORTH] && lastMove[LX200_EAST])
+ strcpy(combinedDir, "North East");
+ else if (lastMove[LX200_SOUTH] && lastMove[LX200_WEST])
+ strcpy(combinedDir, "South West");
+ else if (lastMove[LX200_SOUTH] && lastMove[LX200_EAST])
+ strcpy(combinedDir, "South East");
+ else
+ strcpy(combinedDir, Direction[index]);
+
+ IDSetSwitch(&MovementSP, "Moving %s...", combinedDir);
+ }
+ return;
+ }
+
+ // Tracking mode
+ if (!strcmp (name, TrackModeSP.name))
+ {
+ if (checkPower(&TrackModeSP))
+ return;
+
+ IUResetSwitches(&TrackModeSP);
+ IUUpdateSwitches(&TrackModeSP, states, names, n);
+ trackingMode = getOnSwitch(&TrackModeSP);
+
+ if ( ( err = selectAPTrackingMode(trackingMode) < 0) )
+ {
+ handleError(&TrackModeSP, err, "Setting tracking mode.");
+ return;
+ }
+
+
+ TrackModeSP.s = IPS_OK;
+ IDSetSwitch(&TrackModeSP, NULL);
+ return;
+ }
+
+}
+
+void APMount::handleError(ISwitchVectorProperty *svp, int err, const char *msg)
+{
+
+ svp->s = IPS_ALERT;
+
+ /* First check to see if the telescope is connected */
+ if (testAP())
+ {
+ /* The telescope is off locally */
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_BUSY;
+ IDSetSwitch(&PowerSP, "Telescope is not responding to commands, will retry in 10 seconds.");
+
+ IDSetSwitch(svp, NULL);
+ IEAddTimer(10000, retryConnection, NULL);
+ return;
+ }
+
+ /* If the error is a time out, then the device doesn't support this property or busy*/
+ if (err == -2)
+ {
+ svp->s = IPS_ALERT;
+ IDSetSwitch(svp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
+ }
+ else
+ /* Changing property failed, user should retry. */
+ IDSetSwitch( svp , "%s failed.", msg);
+
+ fault = true;
+}
+
+void APMount::handleError(INumberVectorProperty *nvp, int err, const char *msg)
+{
+
+ nvp->s = IPS_ALERT;
+
+ /* First check to see if the telescope is connected */
+ if (testAP())
+ {
+ /* The telescope is off locally */
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_BUSY;
+ IDSetSwitch(&PowerSP, "Telescope is not responding to commands, will retry in 10 seconds.");
+
+ IDSetNumber(nvp, NULL);
+ IEAddTimer(10000, retryConnection, NULL);
+ return;
+ }
+
+ /* If the error is a time out, then the device doesn't support this property */
+ if (err == -2)
+ {
+ nvp->s = IPS_ALERT;
+ IDSetNumber(nvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
+ }
+ else
+ /* Changing property failed, user should retry. */
+ IDSetNumber( nvp , "%s failed.", msg);
+
+ fault = true;
+}
+
+void APMount::handleError(ITextVectorProperty *tvp, int err, const char *msg)
+{
+
+ tvp->s = IPS_ALERT;
+
+ /* First check to see if the telescope is connected */
+ if (testAP())
+ {
+ /* The telescope is off locally */
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_BUSY;
+ IDSetSwitch(&PowerSP, "Telescope is not responding to commands, will retry in 10 seconds.");
+
+ IDSetText(tvp, NULL);
+ IEAddTimer(10000, retryConnection, NULL);
+ return;
+ }
+
+ /* If the error is a time out, then the device doesn't support this property */
+ if (err == -2)
+ {
+ tvp->s = IPS_ALERT;
+ IDSetText(tvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
+ }
+
+ else
+ /* Changing property failed, user should retry. */
+ IDSetText( tvp , "%s failed.", msg);
+
+ fault = true;
+}
+
+ void APMount::correctFault()
+ {
+
+ fault = false;
+ IDMessage(mydev, "Telescope is online.");
+
+ }
+
+bool APMount::isTelescopeOn(void)
+{
+ if (simulation) return true;
+
+ return (PowerSP.sp[0].s == ISS_ON);
+}
+
+static void retryConnection(void * p)
+{
+ p=p;
+
+ if (testAP())
+ telescope->connectionLost();
+ else
+ telescope->connectionResumed();
+}
+
+void APMount::ISPoll()
+{
+ double dx, dy;
+ int err=0;
+
+ if (!isTelescopeOn())
+ return;
+
+ switch (EqNP.s)
+ {
+ case IPS_IDLE:
+ getLX200RA(&currentRA);
+ getLX200DEC(&currentDEC);
+
+ if ( fabs (currentRA - lastRA) > 0.01 || fabs (currentDEC - lastDEC) > 0.01)
+ {
+ lastRA = currentRA;
+ lastDEC = currentDEC;
+ IDSetNumber (&EqNP, NULL);
+ }
+ break;
+
+ case IPS_BUSY:
+ getLX200RA(&currentRA);
+ getLX200DEC(&currentDEC);
+ dx = targetRA - currentRA;
+ dy = targetDEC - currentDEC;
+
+ IDLog("targetRA is %g, currentRA is %g\n", targetRA, currentRA);
+ IDLog("targetDEC is %g, currentDEC is %g\n*************************\n", targetDEC, currentDEC);
+
+ // Wait until acknowledged or within threshold
+ if (fabs(dx) <= RA_THRESHOLD && fabs(dy) <= DEC_THRESHOLD)
+ {
+
+ lastRA = currentRA;
+ lastDEC = currentDEC;
+ IUResetSwitches(&OnCoordSetSP);
+ OnCoordSetSP.s = IPS_OK;
+ EqNP.s = IPS_OK;
+ IDSetNumber (&EqNP, NULL);
+
+ switch (currentSet)
+ {
+ case LX200_SLEW:
+ OnCoordSetSP.sp[0].s = ISS_ON;
+ IDSetSwitch (&OnCoordSetSP, "Slew is complete.");
+ break;
+
+ case LX200_TRACK:
+ OnCoordSetSP.sp[1].s = ISS_ON;
+ IDSetSwitch (&OnCoordSetSP, "Slew is complete. Tracking...");
+ break;
+
+ case LX200_SYNC:
+ break;
+ }
+
+ } else
+ IDSetNumber (&EqNP, NULL);
+ break;
+
+ case IPS_OK:
+
+ if ( (err = getLX200RA(&currentRA)) < 0 || (err = getLX200DEC(&currentDEC)) < 0)
+ {
+ handleError(&EqNP, err, "Getting RA/DEC");
+ return;
+ }
+
+ if (fault)
+ correctFault();
+
+ if ( (currentRA != lastRA) || (currentDEC != lastDEC))
+ {
+ lastRA = currentRA;
+ lastDEC = currentDEC;
+ IDSetNumber (&EqNP, NULL);
+ }
+ break;
+
+
+ case IPS_ALERT:
+ break;
+ }
+
+ switch (MovementSP.s)
+ {
+ case IPS_IDLE:
+ break;
+ case IPS_BUSY:
+ getLX200RA(&currentRA);
+ getLX200DEC(&currentDEC);
+ IDSetNumber (&EqNP, NULL);
+ break;
+ case IPS_OK:
+ break;
+ case IPS_ALERT:
+ break;
+ }
+
+ switch (FocusTimerNP.s)
+ {
+ case IPS_IDLE:
+ break;
+
+ case IPS_BUSY:
+ FocusTimerN[0].value--;
+
+ if (FocusTimerN[0].value == 0)
+ {
+
+ if ( ( err = setFocuserSpeedMode(0) < 0) )
+ {
+ handleError(&FocusSpeedNP, err, "setting focuser speed mode");
+ IDLog("Error setting focuser speed mode\n");
+ return;
+ }
+
+
+ FocusMotionSP.s = IPS_IDLE;
+ FocusTimerNP.s = IPS_OK;
+ FocusSpeedNP.s = IPS_OK;
+
+ IUResetSwitches(&FocusMotionSP);
+ FocusSpeedN[0].value = 0;
+
+ IDSetNumber(&FocusSpeedNP, NULL);
+ IDSetSwitch(&FocusMotionSP, NULL);
+ }
+
+ IDSetNumber(&FocusTimerNP, NULL);
+ break;
+
+ case IPS_OK:
+ break;
+
+ case IPS_ALERT:
+ break;
+ }
+
+
+}
+
+void APMount::getBasicData()
+{
+
+ // #1 Save current time
+ IUSaveText(&UTCT[0], timestamp());
+ IDLog("PC UTC time is %s\n", UTCT[0].text);
+
+ // #2 Make sure format is long
+ checkLX200Format();
+ timeFormat = LX200_24;
+
+ // #3 Get current RA/DEC
+ getLX200RA(&currentRA);
+ getLX200DEC(&currentDEC);
+ targetRA = currentRA;
+ targetDEC = currentDEC;
+
+ IDSetNumber (&EqNP, NULL);
+ updateLocation();
+ updateTime();
+
+}
+
+int APMount::handleCoordSet()
+{
+
+ int err;
+ char syncString[256];
+ char RAStr[32], DecStr[32];
+ double dx, dy;
+
+ switch (currentSet)
+ {
+
+ // Slew
+ case LX200_SLEW:
+ lastSet = LX200_SLEW;
+ if (EqNP.s == IPS_BUSY)
+ {
+ IDLog("Aboring Slew\n");
+ abortSlew();
+
+ // sleep for 100 mseconds
+ usleep(100000);
+ }
+
+ if ((err = Slew()))
+ {
+ slewError(err);
+ return (-1);
+ }
+
+ EqNP.s = IPS_BUSY;
+ fs_sexa(RAStr, targetRA, 2, 3600);
+ fs_sexa(DecStr, targetDEC, 2, 3600);
+ IDSetNumber(&EqNP, "Slewing to JNow RA %s - DEC %s", RAStr, DecStr);
+ IDLog("Slewing to JNow RA %s - DEC %s\n", RAStr, DecStr);
+ break;
+
+ // Track
+ case LX200_TRACK:
+ IDLog("We're in LX200_TRACK\n");
+ if (EqNP.s == IPS_BUSY)
+ {
+ IDLog("Aboring Slew\n");
+ abortSlew();
+
+ // sleep for 200 mseconds
+ usleep(200000);
+ }
+
+ dx = fabs ( targetRA - currentRA );
+ dy = fabs (targetDEC - currentDEC);
+
+
+ if (dx >= TRACKING_THRESHOLD || dy >= TRACKING_THRESHOLD)
+ {
+ IDLog("Exceeded Tracking threshold, will attempt to slew to the new target.\n");
+ IDLog("targetRA is %g, currentRA is %g\n", targetRA, currentRA);
+ IDLog("targetDEC is %g, currentDEC is %g\n*************************\n", targetDEC, currentDEC);
+
+ if ((err = Slew()))
+ {
+ slewError(err);
+ return (-1);
+ }
+
+ fs_sexa(RAStr, targetRA, 2, 3600);
+ fs_sexa(DecStr, targetDEC, 2, 3600);
+ EqNP.s = IPS_BUSY;
+ IDSetNumber(&EqNP, "Slewing to JNow RA %s - DEC %s", RAStr, DecStr);
+ IDLog("Slewing to JNow RA %s - DEC %s\n", RAStr, DecStr);
+ }
+ else
+ {
+ IDLog("Tracking called, but tracking threshold not reached yet.\n");
+ EqNP.s = IPS_OK;
+ EqNP.np[0].value = currentRA;
+ EqNP.np[1].value = currentDEC;
+
+ if (lastSet != LX200_TRACK)
+ IDSetNumber(&EqNP, "Tracking...");
+ else
+ IDSetNumber(&EqNP, NULL);
+ }
+ lastSet = LX200_TRACK;
+ break;
+
+ // Sync
+ case LX200_SYNC:
+ lastSet = LX200_SYNC;
+ EqNP.s = IPS_IDLE;
+
+ if ( ( err = Sync(syncString) < 0) )
+ {
+ IDSetNumber( &EqNP , "Synchronization failed.");
+ return (-1);
+ }
+
+ EqNP.s = IPS_OK;
+ IDLog("Synchronization successful %s\n", syncString);
+ IDSetNumber(&EqNP, "Synchronization successful.");
+ break;
+ }
+
+ return (0);
+
+}
+
+int APMount::getOnSwitch(ISwitchVectorProperty *sp)
+{
+ for (int i=0; i < sp->nsp ; i++)
+ if (sp->sp[i].s == ISS_ON)
+ return i;
+
+ return -1;
+}
+
+
+int APMount::checkPower(ISwitchVectorProperty *sp)
+{
+ if (simulation) return 0;
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(sp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", sp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", sp->label);
+
+ sp->s = IPS_IDLE;
+ IDSetSwitch(sp, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int APMount::checkPower(INumberVectorProperty *np)
+{
+ if (simulation) return 0;
+
+ if (PowerSP.s != IPS_OK)
+ {
+
+ if (!strcmp(np->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", np->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", np->label);
+
+ np->s = IPS_IDLE;
+ IDSetNumber(np, NULL);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+int APMount::checkPower(ITextVectorProperty *tp)
+{
+
+ if (simulation) return 0;
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(tp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", tp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", tp->label);
+
+ tp->s = IPS_IDLE;
+ IDSetText(tp, NULL);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+void APMount::powerTelescope()
+{
+ switch (PowerSP.sp[0].s)
+ {
+ case ISS_ON:
+
+ if (simulation)
+ {
+ PowerSP.s = IPS_OK;
+ IDSetSwitch (&PowerSP, "Simulated telescope is online.");
+ updateTime();
+ return;
+ }
+
+ if (Connect(PortT[0].text))
+ {
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch (&PowerSP, "Error connecting to port %s\n", PortT[0].text);
+ return;
+ }
+
+ if (testAP())
+ {
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch (&PowerSP, "Error connecting to Telescope. Telescope is offline.");
+ return;
+ }
+
+ IDLog("telescope test successfful\n");
+ PowerSP.s = IPS_OK;
+ IDSetSwitch (&PowerSP, "Telescope is online. Retrieving basic data...");
+ getBasicData();
+ break;
+
+ case ISS_OFF:
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_IDLE;
+ IDSetSwitch (&PowerSP, "Telescope is offline.");
+ IDLog("Telescope is offline.");
+ Disconnect();
+ break;
+
+ }
+
+}
+
+void APMount::slewError(int slewCode)
+{
+ OnCoordSetSP.s = IPS_IDLE;
+ ParkSP.s = IPS_IDLE;
+ IDSetSwitch(&ParkSP, NULL);
+
+ if (slewCode == 1)
+ IDSetSwitch (&OnCoordSetSP, "Object below horizon.");
+ else if (slewCode == 2)
+ IDSetSwitch (&OnCoordSetSP, "Object below the minimum elevation limit.");
+ else
+ IDSetSwitch (&OnCoordSetSP, "Slew failed.");
+
+
+}
+
+void APMount::enableSimulation(bool enable)
+{
+ simulation = enable;
+
+ if (simulation)
+ IDLog("Warning: Simulation is activated.\n");
+ else
+ IDLog("Simulation is disabled.\n");
+}
+
+void APMount::updateTime()
+{
+
+ char cdate[32];
+ double ctime;
+ int h, m, s;
+ int day, month, year, result;
+ int UTC_h, UTC_month, UTC_year, UTC_day, daysInFeb;
+ bool leapYear;
+
+ tzset();
+
+ UTCOffset = timezoneOffset();
+ IDLog("Daylight: %s - TimeZone: %g\n", daylight ? "Yes" : "No", UTCOffset);
+
+
+ if (simulation)
+ {
+ sprintf(UTCT[0].text, "%d-%02d-%02dT%02d:%02d:%02d", 1979, 6, 25, 3, 30, 30);
+ IDLog("Telescope ISO date and time: %s\n", UTCT[0].text);
+ IDSetText(&TimeTP, NULL);
+ return;
+ }
+
+ getLocalTime24(&ctime);
+ getSexComponents(ctime, &h, &m, &s);
+
+ UTC_h = h;
+
+ if ( (result = getSDTime(&SDTimeN[0].value)) < 0)
+ IDMessage(mydev, "Failed to retrieve siderial time from device.");
+
+ getCalenderDate(cdate);
+
+ result = sscanf(cdate, "%d/%d/%d", &year, &month, &day);
+ if (result != 3) return;
+
+ if (year % 4 == 0)
+ {
+ if (year % 100 == 0)
+ {
+ if (year % 400 == 0)
+ leapYear = true;
+ else
+ leapYear = false;
+ }
+ else
+ leapYear = true;
+ }
+ else
+ leapYear = false;
+
+ daysInFeb = leapYear ? 29 : 28;
+
+ UTC_year = year;
+ UTC_month = month;
+ UTC_day = day;
+
+ IDLog("day: %d - month %d - year: %d\n", day, month, year);
+
+ // we'll have to convert telescope time to UTC manually starting from hour up
+ // seems like a stupid way to do it.. oh well
+ UTC_h = (int) UTCOffset + h;
+ if (UTC_h < 0)
+ {
+ UTC_h += 24;
+ UTC_day--;
+ }
+ else if (UTC_h > 24)
+ {
+ UTC_h -= 24;
+ UTC_day++;
+ }
+
+ switch (UTC_month)
+ {
+ case 1:
+ case 8:
+ if (UTC_day < 1)
+ {
+ UTC_day = 31;
+ UTC_month--;
+ }
+ else if (UTC_day > 31)
+ {
+ UTC_day = 1;
+ UTC_month++;
+ }
+ break;
+
+ case 2:
+ if (UTC_day < 1)
+ {
+ UTC_day = 31;
+ UTC_month--;
+ }
+ else if (UTC_day > daysInFeb)
+ {
+ UTC_day = 1;
+ UTC_month++;
+ }
+ break;
+
+ case 3:
+ if (UTC_day < 1)
+ {
+ UTC_day = daysInFeb;
+ UTC_month--;
+ }
+ else if (UTC_day > 31)
+ {
+ UTC_day = 1;
+ UTC_month++;
+ }
+ break;
+
+ case 4:
+ case 6:
+ case 9:
+ case 11:
+ if (UTC_day < 1)
+ {
+ UTC_day = 31;
+ UTC_month--;
+ }
+ else if (UTC_day > 30)
+ {
+ UTC_day = 1;
+ UTC_month++;
+ }
+ break;
+
+ case 5:
+ case 7:
+ case 10:
+ case 12:
+ if (UTC_day < 1)
+ {
+ UTC_day = 30;
+ UTC_month--;
+ }
+ else if (UTC_day > 31)
+ {
+ UTC_day = 1;
+ UTC_month++;
+ }
+ break;
+
+ }
+
+ if (UTC_month < 1)
+ {
+ UTC_month = 12;
+ UTC_year--;
+ }
+ else if (UTC_month > 12)
+ {
+ UTC_month = 1;
+ UTC_year++;
+ }
+
+ /* Format it into ISO 8601 */
+ sprintf(UTCT[0].text, "%d-%02d-%02dT%02d:%02d:%02d", UTC_year, UTC_month, UTC_day, UTC_h, m, s);
+
+ IDLog("Local telescope time: %02d:%02d:%02d\n", h, m , s);
+ IDLog("Telescope SD Time is: %g\n", SDTimeN[0].value);
+ IDLog("UTC date and time: %s\n", UTCT[0].text);
+
+
+ // Let's send everything to the client
+ IDSetText(&TimeTP, NULL);
+ IDSetNumber(&SDTimeNP, NULL);
+
+}
+
+void APMount::updateLocation()
+{
+
+ int dd = 0, mm = 0, err = 0;
+
+ if ( (err = getSiteLatitude(&dd, &mm)) < 0)
+ IDMessage(mydev, "Failed to get site latitude from device.");
+ else
+ {
+ if (dd > 0)
+ GeoNP.np[0].value = dd + mm/60.0;
+ else
+ GeoNP.np[0].value = dd - mm/60.0;
+
+ IDLog("Astro-Physics Latitude: %d:%d\n", dd, mm);
+ IDLog("INDI Latitude: %g\n", GeoNP.np[0].value);
+ }
+
+ if ( (err = getSiteLongitude(&dd, &mm)) < 0)
+ IDMessage(mydev, "Failed to get site longitude from device.");
+ else
+ {
+ if (dd > 0) GeoNP.np[1].value = 360.0 - (dd + mm/60.0);
+ else GeoNP.np[1].value = (dd - mm/60.0) * -1.0;
+
+ IDLog("Astro-Physics Longitude: %d:%d\n", dd, mm);
+ IDLog("INDI Longitude: %g\n", GeoNP.np[1].value);
+ }
+
+ IDSetNumber (&GeoNP, NULL);
+
+}
+
+void APMount::connectionLost()
+{
+ PowerSP.s = IPS_IDLE;
+ IDSetSwitch(&PowerSP, "The connection to the telescope is lost.");
+ return;
+
+}
+
+void APMount::connectionResumed()
+{
+ PowerS[0].s = ISS_ON;
+ PowerS[1].s = ISS_OFF;
+ PowerSP.s = IPS_OK;
+
+ IDSetSwitch(&PowerSP, "The connection to the telescope has been resumed.");
+}
+
+
diff --git a/kstars/kstars/indi/apmount.h b/kstars/kstars/indi/apmount.h
new file mode 100644
index 00000000..3188b933
--- /dev/null
+++ b/kstars/kstars/indi/apmount.h
@@ -0,0 +1,144 @@
+/*
+ Astro-Physics driver
+ Copyright (C) 2005 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef ASTROPHYSICS_H
+#define ASTROPHYSICS_H
+
+#include "indidevapi.h"
+#include "indicom.h"
+
+#define POLLMS 1000 /* poll period, ms */
+#define mydev "Astro-Physics" /* The device name */
+
+
+
+/* equatorial position */
+
+// N.B. No Static identifier as it is needed for external linkage
+
+
+
+class APMount
+{
+ public:
+ APMount();
+ ~APMount();
+
+ void ISGetProperties (const char *dev);
+ void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+ void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+ void ISPoll ();
+
+ void connectionLost();
+ void connectionResumed();
+
+private:
+
+ void initProperties();
+
+ /* Switches */
+ ISwitch AlignmentS [2];
+ ISwitch PowerS[2];
+ ISwitch OnCoordSetS[3];
+ ISwitch TrackModeS[4];
+ ISwitch AbortSlewS[1];
+ ISwitch ParkS[2];
+ ISwitch MovementS[4];
+ ISwitch FocusMotionS[2];
+
+ /* Texts */
+ IText PortT[1];
+ IText UTCT[1];
+ IText ObjectT[1];
+
+ /* Numbers */
+ INumber EqN[2];
+ INumber GeoN[2];
+ INumber FocusTimerN[1];
+ INumber SDTimeN[1];
+ INumber HorN[2];
+ INumber FocusSpeedN[1];
+
+ /* Switch Vectors */
+ ISwitchVectorProperty PowerSP;
+ ISwitchVectorProperty AlignmentSP;
+ ISwitchVectorProperty OnCoordSetSP;
+ ISwitchVectorProperty AbortSlewSP;
+ ISwitchVectorProperty ParkSP;
+ ISwitchVectorProperty TrackModeSP;
+ ISwitchVectorProperty MovementSP;
+ ISwitchVectorProperty FocusMotionSP;
+
+ /* Number Vectors */
+ INumberVectorProperty EqNP;
+ INumberVectorProperty GeoNP;
+ INumberVectorProperty FocusTimerNP;
+ INumberVectorProperty SDTimeNP;
+ INumberVectorProperty HorNP;
+ INumberVectorProperty FocusSpeedNP;
+
+ /* Text Vectors */
+ ITextVectorProperty PortTP;
+ ITextVectorProperty TimeTP;
+ ITextVectorProperty ObjectTP;
+
+ void getBasicData();
+ int checkPower(INumberVectorProperty *np);
+ int checkPower(ISwitchVectorProperty *sp);
+ int checkPower(ITextVectorProperty *tp);
+ void handleError(ISwitchVectorProperty *svp, int err, const char *msg);
+ void handleError(INumberVectorProperty *nvp, int err, const char *msg);
+ void handleError(ITextVectorProperty *tvp, int err, const char *msg);
+ bool isTelescopeOn(void);
+ void powerTelescope();
+ void slewError(int slewCode);
+ void getAlignment();
+ int handleCoordSet();
+ int getOnSwitch(ISwitchVectorProperty *sp);
+ void correctFault();
+ void enableSimulation(bool enable);
+ void updateTime();
+ void updateLocation();
+
+
+ protected:
+ int timeFormat;
+ int currentSiteNum;
+ int trackingMode;
+
+ double JD;
+ double targetRA;
+ double targetDEC;
+ double lastRA;
+ double lastDEC;
+ double UTCOffset;
+ bool fault;
+ bool simulation;
+
+ struct tm *localTM;
+
+ int currentSet;
+ int lastSet;
+ int lastMove[4];
+
+};
+
+#endif
diff --git a/kstars/kstars/indi/apogee/Apn.h b/kstars/kstars/indi/apogee/Apn.h
new file mode 100644
index 00000000..c5071e50
--- /dev/null
+++ b/kstars/kstars/indi/apogee/Apn.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#define APN_DRIVER_VERSION "2.0.13.0"
+
+#define APN_HBINNING_MAX 10
+#define APN_VBINNING_MAX 2048
+
+#define APN_TIMER_RESOLUTION 0.00000256
+#define APN_PERIOD_TIMER_RESOLUTION 0.000000040
+
+#define APN_TIMER_OFFSET_COUNT 3
+
+#define APN_SEQUENCE_DELAY_RESOLUTION 0.000327
+#define APN_SEQUENCE_DELAY_LIMIT 21.429945
+
+#define APN_EXPOSURE_TIME_MIN 0.00001 // 10us is the defined min.
+#define APN_EXPOSURE_TIME_MAX 10990.0 // seconds
+
+#define APN_TDI_RATE_RESOLUTION 0.00000512
+#define APN_TDI_RATE_MIN 0.00000512
+#define APN_TDI_RATE_MAX 0.336
+
+#define APN_VOLTAGE_RESOLUTION 0.00439453
+
+#define APN_SHUTTER_CLOSE_DIFF 0.00001024
+
+#define APN_STROBE_POSITION_MIN 0.00000331
+#define APN_STROBE_POSITION_MAX 0.1677
+#define APN_STROBE_PERIOD_MIN 0.000000045
+#define APN_STROBE_PERIOD_MAX 0.0026
+
+#define APN_TEMP_COUNTS 4096
+#define APN_TEMP_KELVIN_SCALE_OFFSET 273.16
+
+#define APN_TEMP_SETPOINT_MIN 213
+#define APN_TEMP_SETPOINT_MAX 313
+
+#define APN_TEMP_HEATSINK_MIN 240
+#define APN_TEMP_HEATSINK_MAX 340
+
+#define APN_TEMP_SETPOINT_ZERO_POINT 2458
+#define APN_TEMP_HEATSINK_ZERO_POINT 1351
+
+#define APN_TEMP_DEGREES_PER_BIT 0.024414
+
+#define APN_FAN_SPEED_OFF 0
+#define APN_FAN_SPEED_LOW 3100
+#define APN_FAN_SPEED_MEDIUM 3660
+#define APN_FAN_SPEED_HIGH 4095
diff --git a/kstars/kstars/indi/apogee/ApnCamData.cpp b/kstars/kstars/indi/apogee/ApnCamData.cpp
new file mode 100644
index 00000000..da339741
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData.cpp
@@ -0,0 +1,130 @@
+// ApnCamData.cpp: implementation of the CApnCamData class.
+//
+// Copyright (c) 2003, 2004 Apogee Instruments, Inc.
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ApnCamData.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CApnCamData::CApnCamData()
+{
+ init_vpattern();
+
+ init_hpattern( &m_ClampPatternSixteen );
+ init_hpattern( &m_SkipPatternSixteen );
+ init_hpattern( &m_RoiPatternSixteen );
+
+ init_hpattern( &m_ClampPatternTwelve );
+ init_hpattern( &m_SkipPatternTwelve );
+ init_hpattern( &m_RoiPatternTwelve );
+}
+
+CApnCamData::~CApnCamData()
+{
+ clear_vpattern();
+
+ clear_hpattern( &m_ClampPatternSixteen );
+ clear_hpattern( &m_SkipPatternSixteen );
+ clear_hpattern( &m_RoiPatternSixteen );
+
+ clear_hpattern( &m_ClampPatternTwelve );
+ clear_hpattern( &m_SkipPatternTwelve );
+ clear_hpattern( &m_RoiPatternTwelve );
+}
+
+
+void CApnCamData::init_vpattern( )
+{
+ // OutputDebugString( "init_vpattern()" );
+
+ m_VerticalPattern.Mask = 0x0;
+ m_VerticalPattern.NumElements = 0;
+ m_VerticalPattern.PatternData = NULL;
+}
+
+
+void CApnCamData::clear_vpattern( )
+{
+ // OutputDebugString( "clear_vpattern()" );
+
+ m_VerticalPattern.Mask = 0x0;
+ m_VerticalPattern.NumElements = 0;
+
+ if ( m_VerticalPattern.PatternData != NULL )
+ {
+ free( m_VerticalPattern.PatternData );
+ m_VerticalPattern.PatternData = NULL;
+ }
+}
+
+
+void CApnCamData::init_hpattern( APN_HPATTERN_FILE *Pattern )
+{
+ int Counter;
+
+ // OutputDebugString( "init_hpattern()" );
+
+ Pattern->Mask = 0x0;
+ Pattern->RefNumElements = 0;
+ Pattern->SigNumElements = 0;
+ Pattern->BinningLimit = 0;
+
+ Pattern->RefPatternData = NULL;
+ Pattern->SigPatternData = NULL;
+
+ for ( Counter=0; Counter<APN_MAX_HBINNING; Counter++ )
+ {
+ Pattern->BinNumElements[Counter] = 0;
+ Pattern->BinPatternData[Counter] = NULL;
+ }
+}
+
+
+void CApnCamData::clear_hpattern( APN_HPATTERN_FILE *Pattern )
+{
+ int Counter;
+ // char szMsg[80];
+
+ // OutputDebugString( "clear_hpattern()" );
+
+ Pattern->Mask = 0x0;
+ Pattern->RefNumElements = 0;
+ Pattern->SigNumElements = 0;
+ Pattern->BinningLimit = 0;
+
+ if ( Pattern->RefPatternData != NULL )
+ {
+ // OutputDebugString( "Freeing Allocated Reference Pattern Memory" );
+ free( Pattern->RefPatternData );
+
+ Pattern->RefPatternData = NULL;
+ }
+ if ( Pattern->SigPatternData != NULL )
+ {
+ // OutputDebugString( "Freeing Allocated Signal Pattern Memory" );
+ free( Pattern->SigPatternData );
+
+ Pattern->SigPatternData = NULL;
+ }
+
+ for ( Counter=0; Counter<APN_MAX_HBINNING; Counter++ )
+ {
+ Pattern->BinNumElements[Counter] = 0;
+ if ( Pattern->BinPatternData[Counter] != NULL )
+ {
+ // sprintf( szMsg, "Freeing Allocated Binning Pattern Memory (Binning = %d)", Counter+1 );
+ // OutputDebugString( szMsg );
+ free( Pattern->BinPatternData[Counter] );
+
+ Pattern->BinPatternData[Counter] = NULL;
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData.h b/kstars/kstars/indi/apogee/ApnCamData.h
new file mode 100644
index 00000000..7ec3539d
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData.h
@@ -0,0 +1,124 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+// ApnCamData.h: interface for the CApnCamData class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_APNCAMDATA_H__32231556_A1FD_421B_94F8_295D4148E195__INCLUDED_)
+#define AFX_APNCAMDATA_H__32231556_A1FD_421B_94F8_295D4148E195__INCLUDED_
+
+#define APN_MAX_HBINNING 10
+#define APN_MAX_PATTERN_ENTRIES 256
+
+
+typedef struct _APN_VPATTERN_FILE {
+ unsigned short Mask;
+ unsigned short NumElements;
+ unsigned short *PatternData;
+} APN_VPATTERN_FILE;
+
+typedef struct _APN_HPATTERN_FILE {
+ unsigned short Mask;
+ unsigned short BinningLimit;
+ unsigned short RefNumElements;
+ unsigned short BinNumElements[APN_MAX_HBINNING];
+ unsigned short SigNumElements;
+ unsigned short *RefPatternData;
+ unsigned short *BinPatternData[APN_MAX_HBINNING];
+ unsigned short *SigPatternData;
+} APN_HPATTERN_FILE;
+
+
+class CApnCamData
+{
+public:
+ CApnCamData();
+ virtual ~CApnCamData();
+
+ virtual void Initialize() = 0;
+
+
+ char m_Sensor[20];
+ char m_CameraModel[20];
+
+ unsigned short m_CameraId;
+
+ bool m_InterlineCCD;
+ bool m_SupportsSerialA;
+ bool m_SupportsSerialB;
+ bool m_SensorTypeCCD;
+
+ unsigned short m_TotalColumns;
+ unsigned short m_ImagingColumns;
+
+ unsigned short m_ClampColumns;
+ unsigned short m_PreRoiSkipColumns;
+ unsigned short m_PostRoiSkipColumns;
+ unsigned short m_OverscanColumns;
+
+ unsigned short m_TotalRows;
+ unsigned short m_ImagingRows;
+
+ unsigned short m_UnderscanRows;
+ unsigned short m_OverscanRows;
+
+ unsigned short m_VFlushBinning;
+
+ bool m_EnableSingleRowOffset;
+ unsigned short m_RowOffsetBinning;
+
+ bool m_HFlushDisable;
+
+ unsigned short m_ShutterCloseDelay;
+
+ double m_PixelSizeX;
+ double m_PixelSizeY;
+
+ bool m_Color;
+
+ double m_ReportedGainSixteenBit;
+
+ double m_MinSuggestedExpTime;
+
+ bool m_CoolingSupported;
+ bool m_RegulatedCoolingSupported;
+
+ double m_TempSetPoint;
+ unsigned short m_TempRampRateOne;
+ unsigned short m_TempRampRateTwo;
+ double m_TempBackoffPoint;
+
+ unsigned short m_DefaultGainTwelveBit;
+ unsigned short m_DefaultOffsetTwelveBit;
+ unsigned short m_DefaultRVoltage;
+
+
+ // Pattern Files
+ APN_VPATTERN_FILE m_VerticalPattern;
+
+ APN_HPATTERN_FILE m_ClampPatternSixteen;
+ APN_HPATTERN_FILE m_SkipPatternSixteen;
+ APN_HPATTERN_FILE m_RoiPatternSixteen;
+
+ APN_HPATTERN_FILE m_ClampPatternTwelve;
+ APN_HPATTERN_FILE m_SkipPatternTwelve;
+ APN_HPATTERN_FILE m_RoiPatternTwelve;
+
+
+private:
+
+ void init_vpattern( );
+ void clear_vpattern( );
+
+ void init_hpattern( APN_HPATTERN_FILE *Pattern );
+ void clear_hpattern( APN_HPATTERN_FILE *Pattern );
+
+};
+
+#endif // !defined(AFX_APNCAMDATA_H__32231556_A1FD_421B_94F8_295D4148E195__INCLUDED_)
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD3011HS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD3011HS.cpp
new file mode 100644
index 00000000..8ea6b7de
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD3011HS.cpp
@@ -0,0 +1,582 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD3011HS.cpp: Implementation file for the CApnCamData_CCD3011HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD3011HS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD3011HS::CApnCamData_CCD3011HS()
+{
+}
+
+
+CApnCamData_CCD3011HS::~CApnCamData_CCD3011HS()
+{
+}
+
+
+void CApnCamData_CCD3011HS::Initialize()
+{
+ strcpy( m_Sensor, "CCD3011HS" );
+ strcpy( m_CameraModel, "30" );
+ m_CameraId = 21;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1040;
+ m_ImagingColumns = 1024;
+ m_ClampColumns = 8;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 8;
+ m_TotalRows = 256;
+ m_ImagingRows = 256;
+ m_UnderscanRows = 0;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 26;
+ m_PixelSizeY = 26;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD3011HS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 247;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A,
+ 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A,
+ 0x000A, 0x000A, 0x000A, 0x000A, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD3011HS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD3011HS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD3011HS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD3011HS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD3011HS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD3011HS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD3011HS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD3011HS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD3011HS.h
new file mode 100644
index 00000000..6ffa3a6c
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD3011HS.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD3011HS.h: Interface file for the CApnCamData_CCD3011HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD3011HS : public CApnCamData
+{
+public:
+ CApnCamData_CCD3011HS();
+ virtual ~CApnCamData_CCD3011HS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD3011LS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD3011LS.cpp
new file mode 100644
index 00000000..565c3f88
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD3011LS.cpp
@@ -0,0 +1,572 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD3011LS.cpp: Implementation file for the CApnCamData_CCD3011LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD3011LS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD3011LS::CApnCamData_CCD3011LS()
+{
+}
+
+
+CApnCamData_CCD3011LS::~CApnCamData_CCD3011LS()
+{
+}
+
+
+void CApnCamData_CCD3011LS::Initialize()
+{
+ strcpy( m_Sensor, "CCD3011LS" );
+ strcpy( m_CameraModel, "30" );
+ m_CameraId = 20;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1040;
+ m_ImagingColumns = 1024;
+ m_ClampColumns = 8;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 8;
+ m_TotalRows = 256;
+ m_ImagingRows = 256;
+ m_UnderscanRows = 0;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 26;
+ m_PixelSizeY = 26;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD3011LS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 247;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A,
+ 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A,
+ 0x000A, 0x000A, 0x000A, 0x000A, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD3011LS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD3011LS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD3011LS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD3011LS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD3011LS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD3011LS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD3011LS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD3011LS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD3011LS.h
new file mode 100644
index 00000000..018d2e23
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD3011LS.h
@@ -0,0 +1,41 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD3011LS.h: Interface file for the CApnCamData_CCD3011LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD3011LS : public CApnCamData
+{
+public:
+ CApnCamData_CCD3011LS();
+ virtual ~CApnCamData_CCD3011LS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4020HS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD4020HS.h
new file mode 100644
index 00000000..8d1c8b69
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4020HS.h
@@ -0,0 +1 @@
+
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4240HS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD4240HS.cpp
new file mode 100644
index 00000000..cfb84f14
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4240HS.cpp
@@ -0,0 +1,572 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4240HS.cpp: Implementation file for the CApnCamData_CCD4240HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD4240HS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD4240HS::CApnCamData_CCD4240HS()
+{
+}
+
+
+CApnCamData_CCD4240HS::~CApnCamData_CCD4240HS()
+{
+}
+
+
+void CApnCamData_CCD4240HS::Initialize()
+{
+ strcpy( m_Sensor, "CCD4240HS" );
+ strcpy( m_CameraModel, "42" );
+ m_CameraId = 16;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 2148;
+ m_ImagingColumns = 2048;
+ m_ClampColumns = 50;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 50;
+ m_TotalRows = 2052;
+ m_ImagingRows = 2048;
+ m_UnderscanRows = 2;
+ m_OverscanRows = 2;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 600;
+ m_PixelSizeX = 13.5;
+ m_PixelSizeY = 13.5;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD4240HS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 247;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A,
+ 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A,
+ 0x000A, 0x000A, 0x000A, 0x000A, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD4240HS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4240HS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4240HS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4240HS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4240HS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4240HS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4240HS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4240HS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD4240HS.h
new file mode 100644
index 00000000..612ebdd0
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4240HS.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4240HS.h: Interface file for the CApnCamData_CCD4240HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD4240HS : public CApnCamData
+{
+public:
+ CApnCamData_CCD4240HS();
+ virtual ~CApnCamData_CCD4240HS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4240LS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD4240LS.cpp
new file mode 100644
index 00000000..d768dad0
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4240LS.cpp
@@ -0,0 +1,572 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4240LS.cpp: Implementation file for the CApnCamData_CCD4240LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD4240LS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD4240LS::CApnCamData_CCD4240LS()
+{
+}
+
+
+CApnCamData_CCD4240LS::~CApnCamData_CCD4240LS()
+{
+}
+
+
+void CApnCamData_CCD4240LS::Initialize()
+{
+ strcpy( m_Sensor, "CCD4240LS" );
+ strcpy( m_CameraModel, "42" );
+ m_CameraId = 17;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 2148;
+ m_ImagingColumns = 2048;
+ m_ClampColumns = 50;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 50;
+ m_TotalRows = 2052;
+ m_ImagingRows = 2048;
+ m_UnderscanRows = 2;
+ m_OverscanRows = 2;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 600;
+ m_PixelSizeX = 13.5;
+ m_PixelSizeY = 13.5;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD4240LS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 247;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A,
+ 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A,
+ 0x000A, 0x000A, 0x000A, 0x000A, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD4240LS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4240LS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4240LS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4240LS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4240LS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4240LS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4240LS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4240LS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD4240LS.h
new file mode 100644
index 00000000..4767d428
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4240LS.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4240LS.h: Interface file for the CApnCamData_CCD4240LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD4240LS : public CApnCamData
+{
+public:
+ CApnCamData_CCD4240LS();
+ virtual ~CApnCamData_CCD4240LS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4710HS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD4710HS.cpp
new file mode 100644
index 00000000..2b0dde8e
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4710HS.cpp
@@ -0,0 +1,566 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4710HS.cpp: Implementation file for the CApnCamData_CCD4710HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD4710HS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD4710HS::CApnCamData_CCD4710HS()
+{
+}
+
+
+CApnCamData_CCD4710HS::~CApnCamData_CCD4710HS()
+{
+}
+
+
+void CApnCamData_CCD4710HS::Initialize()
+{
+ strcpy( m_Sensor, "CCD4710HS" );
+ strcpy( m_CameraModel, "47" );
+ m_CameraId = 11;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1072;
+ m_ImagingColumns = 1024;
+ m_ClampColumns = 24;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 24;
+ m_TotalRows = 1027;
+ m_ImagingRows = 1024;
+ m_UnderscanRows = 3;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 13;
+ m_PixelSizeY = 13;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD4710HS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 247;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD4710HS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710HS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710HS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 27;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0,
+ 0x00D0, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x8004, 0x8005, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0054, 0x0044
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710HS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710HS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710HS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710HS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4710HS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD4710HS.h
new file mode 100644
index 00000000..b07baedb
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4710HS.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4710HS.h: Interface file for the CApnCamData_CCD4710HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD4710HS : public CApnCamData
+{
+public:
+ CApnCamData_CCD4710HS();
+ virtual ~CApnCamData_CCD4710HS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS.cpp
new file mode 100644
index 00000000..7ab60fb8
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS.cpp
@@ -0,0 +1,572 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4710LS.cpp: Implementation file for the CApnCamData_CCD4710LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD4710LS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD4710LS::CApnCamData_CCD4710LS()
+{
+}
+
+
+CApnCamData_CCD4710LS::~CApnCamData_CCD4710LS()
+{
+}
+
+
+void CApnCamData_CCD4710LS::Initialize()
+{
+ strcpy( m_Sensor, "CCD4710LS" );
+ strcpy( m_CameraModel, "47" );
+ m_CameraId = 10;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1072;
+ m_ImagingColumns = 1024;
+ m_ClampColumns = 24;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 24;
+ m_TotalRows = 1027;
+ m_ImagingRows = 1024;
+ m_UnderscanRows = 3;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 13;
+ m_PixelSizeY = 13;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD4710LS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 247;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD4710LS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS.h
new file mode 100644
index 00000000..417bfc66
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4710LS.h: Interface file for the CApnCamData_CCD4710LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD4710LS : public CApnCamData
+{
+public:
+ CApnCamData_CCD4710LS();
+ virtual ~CApnCamData_CCD4710LS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS2.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS2.cpp
new file mode 100644
index 00000000..a23176f3
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS2.cpp
@@ -0,0 +1,572 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4710LS2.cpp: Implementation file for the CApnCamData_CCD4710LS2 class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD4710LS2.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD4710LS2::CApnCamData_CCD4710LS2()
+{
+}
+
+
+CApnCamData_CCD4710LS2::~CApnCamData_CCD4710LS2()
+{
+}
+
+
+void CApnCamData_CCD4710LS2::Initialize()
+{
+ strcpy( m_Sensor, "CCD4710LS2" );
+ strcpy( m_CameraModel, "47" );
+ m_CameraId = 12;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1072;
+ m_ImagingColumns = 1024;
+ m_ClampColumns = 24;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 24;
+ m_TotalRows = 1027;
+ m_ImagingRows = 1024;
+ m_UnderscanRows = 3;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 13;
+ m_PixelSizeY = 13;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD4710LS2::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 247;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD4710LS2::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS2::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS2::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS2::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS2::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS2::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS2::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS2.h b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS2.h
new file mode 100644
index 00000000..07482590
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS2.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4710LS2.h: Interface file for the CApnCamData_CCD4710LS2 class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD4710LS2 : public CApnCamData
+{
+public:
+ CApnCamData_CCD4710LS2();
+ virtual ~CApnCamData_CCD4710LS2();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS3.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS3.cpp
new file mode 100644
index 00000000..8650c0b2
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS3.cpp
@@ -0,0 +1,571 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4710LS3.cpp: Implementation file for the CApnCamData_CCD4710LS3 class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD4710LS3.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD4710LS3::CApnCamData_CCD4710LS3()
+{
+}
+
+
+CApnCamData_CCD4710LS3::~CApnCamData_CCD4710LS3()
+{
+}
+
+
+void CApnCamData_CCD4710LS3::Initialize()
+{
+ strcpy( m_Sensor, "CCD4710LS3" );
+ strcpy( m_CameraModel, "47" );
+ m_CameraId = 13;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1072;
+ m_ImagingColumns = 1024;
+ m_ClampColumns = 24;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 24;
+ m_TotalRows = 1027;
+ m_ImagingRows = 1024;
+ m_UnderscanRows = 3;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 13;
+ m_PixelSizeY = 13;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD4710LS3::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 247;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD4710LS3::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS3::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS3::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 42;
+ const unsigned short SigNumElements = 56;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006E, 0x006E, 0x006A, 0x006A, 0x106A, 0x106A, 0x106A, 0x007A, 0x007A, 0x007A,
+ 0x007A, 0x007A, 0x0072, 0x0072, 0x0076, 0x0076, 0x0076, 0x0076, 0x0076, 0x0076,
+ 0x0076, 0x0076, 0x0076, 0x0076, 0x00F6, 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6,
+ 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6,
+ 0x00D6, 0x00D6
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x00D6,
+ 0x00D6, 0x00D6, 0x00D6, 0x00D6, 0x0056, 0x0046, 0x0046, 0x0046, 0x0046, 0x0046,
+ 0x0046, 0x0146, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106,
+ 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106,
+ 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106, 0x0106,
+ 0x0106, 0x0106, 0x0106, 0x8106, 0x8107, 0x0406
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D6, 0x00D6
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS3::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS3::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS3::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS3::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS3.h b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS3.h
new file mode 100644
index 00000000..ca8fcce3
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS3.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4710LS3.h: Interface file for the CApnCamData_CCD4710LS3 class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD4710LS3 : public CApnCamData
+{
+public:
+ CApnCamData_CCD4710LS3();
+ virtual ~CApnCamData_CCD4710LS3();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS4.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS4.cpp
new file mode 100644
index 00000000..23cec00b
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS4.cpp
@@ -0,0 +1,571 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4710LS4.cpp: Implementation file for the CApnCamData_CCD4710LS4 class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD4710LS4.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD4710LS4::CApnCamData_CCD4710LS4()
+{
+}
+
+
+CApnCamData_CCD4710LS4::~CApnCamData_CCD4710LS4()
+{
+}
+
+
+void CApnCamData_CCD4710LS4::Initialize()
+{
+ strcpy( m_Sensor, "CCD4710LS4" );
+ strcpy( m_CameraModel, "47" );
+ m_CameraId = 15;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1072;
+ m_ImagingColumns = 1024;
+ m_ClampColumns = 24;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 24;
+ m_TotalRows = 1027;
+ m_ImagingRows = 1024;
+ m_UnderscanRows = 3;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 13;
+ m_PixelSizeY = 13;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD4710LS4::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 247;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD4710LS4::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS4::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS4::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 42;
+ const unsigned short SigNumElements = 56;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8105, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS4::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS4::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS4::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS4::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS4.h b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS4.h
new file mode 100644
index 00000000..18623bc3
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS4.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4710LS4.h: Interface file for the CApnCamData_CCD4710LS4 class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD4710LS4 : public CApnCamData
+{
+public:
+ CApnCamData_CCD4710LS4();
+ virtual ~CApnCamData_CCD4710LS4();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS5.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS5.cpp
new file mode 100644
index 00000000..625bcc5b
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS5.cpp
@@ -0,0 +1,571 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4710LS5.cpp: Implementation file for the CApnCamData_CCD4710LS5 class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD4710LS5.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD4710LS5::CApnCamData_CCD4710LS5()
+{
+}
+
+
+CApnCamData_CCD4710LS5::~CApnCamData_CCD4710LS5()
+{
+}
+
+
+void CApnCamData_CCD4710LS5::Initialize()
+{
+ strcpy( m_Sensor, "CCD4710LS5" );
+ strcpy( m_CameraModel, "47" );
+ m_CameraId = 28;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1072;
+ m_ImagingColumns = 1024;
+ m_ClampColumns = 24;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 24;
+ m_TotalRows = 1027;
+ m_ImagingRows = 1024;
+ m_UnderscanRows = 3;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 13;
+ m_PixelSizeY = 13;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD4710LS5::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 247;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD4710LS5::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS5::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS5::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 42;
+ const unsigned short SigNumElements = 56;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8105, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS5::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS5::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS5::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4710LS5::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS5.h b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS5.h
new file mode 100644
index 00000000..23907e5e
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4710LS5.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4710LS5.h: Interface file for the CApnCamData_CCD4710LS5 class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD4710LS5 : public CApnCamData
+{
+public:
+ CApnCamData_CCD4710LS5();
+ virtual ~CApnCamData_CCD4710LS5();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4720HS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD4720HS.cpp
new file mode 100644
index 00000000..e95d6dc2
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4720HS.cpp
@@ -0,0 +1,550 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4720HS.cpp: Implementation file for the CApnCamData_CCD4720HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD4720HS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD4720HS::CApnCamData_CCD4720HS()
+{
+}
+
+
+CApnCamData_CCD4720HS::~CApnCamData_CCD4720HS()
+{
+}
+
+
+void CApnCamData_CCD4720HS::Initialize()
+{
+ strcpy( m_Sensor, "CCD4720HS" );
+ strcpy( m_CameraModel, "4720" );
+ m_CameraId = 25;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1072;
+ m_ImagingColumns = 1024;
+ m_ClampColumns = 24;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 24;
+ m_TotalRows = 2057;
+ m_ImagingRows = 1024;
+ m_UnderscanRows = 1033;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = true;
+ m_RowOffsetBinning = 1033;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 0;
+ m_PixelSizeX = 13;
+ m_PixelSizeY = 13;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 1.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD4720HS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 23;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0006, 0x0006, 0x0006,
+ 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD4720HS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4720HS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4720HS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4720HS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4720HS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4720HS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4720HS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4720HS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD4720HS.h
new file mode 100644
index 00000000..4616b0fb
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4720HS.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4720HS.h: Interface file for the CApnCamData_CCD4720HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD4720HS : public CApnCamData
+{
+public:
+ CApnCamData_CCD4720HS();
+ virtual ~CApnCamData_CCD4720HS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4720LS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD4720LS.cpp
new file mode 100644
index 00000000..c46098cd
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4720LS.cpp
@@ -0,0 +1,550 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4720LS.cpp: Implementation file for the CApnCamData_CCD4720LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD4720LS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD4720LS::CApnCamData_CCD4720LS()
+{
+}
+
+
+CApnCamData_CCD4720LS::~CApnCamData_CCD4720LS()
+{
+}
+
+
+void CApnCamData_CCD4720LS::Initialize()
+{
+ strcpy( m_Sensor, "CCD4720LS" );
+ strcpy( m_CameraModel, "4720" );
+ m_CameraId = 24;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1072;
+ m_ImagingColumns = 1024;
+ m_ClampColumns = 24;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 24;
+ m_TotalRows = 2057;
+ m_ImagingRows = 1024;
+ m_UnderscanRows = 1033;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = true;
+ m_RowOffsetBinning = 1033;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 0;
+ m_PixelSizeX = 13;
+ m_PixelSizeY = 13;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 1.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD4720LS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 23;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0006, 0x0006, 0x0006,
+ 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD4720LS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4720LS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4720LS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4720LS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4720LS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4720LS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD4720LS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD4720LS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD4720LS.h
new file mode 100644
index 00000000..5ace563c
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD4720LS.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD4720LS.h: Interface file for the CApnCamData_CCD4720LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD4720LS : public CApnCamData
+{
+public:
+ CApnCamData_CCD4720LS();
+ virtual ~CApnCamData_CCD4720LS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD5520HS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD5520HS.cpp
new file mode 100644
index 00000000..657200e3
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD5520HS.cpp
@@ -0,0 +1,572 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD5520HS.cpp: Implementation file for the CApnCamData_CCD5520HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD5520HS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD5520HS::CApnCamData_CCD5520HS()
+{
+}
+
+
+CApnCamData_CCD5520HS::~CApnCamData_CCD5520HS()
+{
+}
+
+
+void CApnCamData_CCD5520HS::Initialize()
+{
+ strcpy( m_Sensor, "CCD5520HS" );
+ strcpy( m_CameraModel, "55" );
+ m_CameraId = 23;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 804;
+ m_ImagingColumns = 770;
+ m_ClampColumns = 17;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 17;
+ m_TotalRows = 1152;
+ m_ImagingRows = 1152;
+ m_UnderscanRows = 0;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 22.5;
+ m_PixelSizeY = 22.5;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD5520HS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 247;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A,
+ 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A,
+ 0x000A, 0x000A, 0x000A, 0x000A, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD5520HS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5520HS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5520HS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5520HS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5520HS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5520HS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5520HS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD5520HS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD5520HS.h
new file mode 100644
index 00000000..0e4c2a34
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD5520HS.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD5520HS.h: Interface file for the CApnCamData_CCD5520HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD5520HS : public CApnCamData
+{
+public:
+ CApnCamData_CCD5520HS();
+ virtual ~CApnCamData_CCD5520HS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD5520LS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD5520LS.cpp
new file mode 100644
index 00000000..1dc66328
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD5520LS.cpp
@@ -0,0 +1,572 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD5520LS.cpp: Implementation file for the CApnCamData_CCD5520LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD5520LS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD5520LS::CApnCamData_CCD5520LS()
+{
+}
+
+
+CApnCamData_CCD5520LS::~CApnCamData_CCD5520LS()
+{
+}
+
+
+void CApnCamData_CCD5520LS::Initialize()
+{
+ strcpy( m_Sensor, "CCD5520LS" );
+ strcpy( m_CameraModel, "55" );
+ m_CameraId = 22;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 804;
+ m_ImagingColumns = 770;
+ m_ClampColumns = 17;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 17;
+ m_TotalRows = 1152;
+ m_ImagingRows = 1152;
+ m_UnderscanRows = 0;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 22.5;
+ m_PixelSizeY = 22.5;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD5520LS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 247;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A,
+ 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A, 0x000A,
+ 0x000A, 0x000A, 0x000A, 0x000A, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C,
+ 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD5520LS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5520LS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5520LS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5520LS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5520LS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5520LS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5520LS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD5520LS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD5520LS.h
new file mode 100644
index 00000000..3f2b18fe
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD5520LS.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD5520LS.h: Interface file for the CApnCamData_CCD5520LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD5520LS : public CApnCamData
+{
+public:
+ CApnCamData_CCD5520LS();
+ virtual ~CApnCamData_CCD5520LS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD5710HS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD5710HS.cpp
new file mode 100644
index 00000000..fd737cbe
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD5710HS.cpp
@@ -0,0 +1,550 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD5710HS.cpp: Implementation file for the CApnCamData_CCD5710HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD5710HS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD5710HS::CApnCamData_CCD5710HS()
+{
+}
+
+
+CApnCamData_CCD5710HS::~CApnCamData_CCD5710HS()
+{
+}
+
+
+void CApnCamData_CCD5710HS::Initialize()
+{
+ strcpy( m_Sensor, "CCD5710HS" );
+ strcpy( m_CameraModel, "57" );
+ m_CameraId = 19;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 536;
+ m_ImagingColumns = 512;
+ m_ClampColumns = 12;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 12;
+ m_TotalRows = 1056;
+ m_ImagingRows = 512;
+ m_UnderscanRows = 536;
+ m_OverscanRows = 8;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = true;
+ m_RowOffsetBinning = 536;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 0;
+ m_PixelSizeX = 13;
+ m_PixelSizeY = 13;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 1.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD5710HS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 23;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0006, 0x0006, 0x0006,
+ 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD5710HS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5710HS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5710HS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5710HS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5710HS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5710HS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5710HS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD5710HS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD5710HS.h
new file mode 100644
index 00000000..f455126e
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD5710HS.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD5710HS.h: Interface file for the CApnCamData_CCD5710HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD5710HS : public CApnCamData
+{
+public:
+ CApnCamData_CCD5710HS();
+ virtual ~CApnCamData_CCD5710HS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD5710LS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD5710LS.cpp
new file mode 100644
index 00000000..438cf29d
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD5710LS.cpp
@@ -0,0 +1,550 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD5710LS.cpp: Implementation file for the CApnCamData_CCD5710LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD5710LS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD5710LS::CApnCamData_CCD5710LS()
+{
+}
+
+
+CApnCamData_CCD5710LS::~CApnCamData_CCD5710LS()
+{
+}
+
+
+void CApnCamData_CCD5710LS::Initialize()
+{
+ strcpy( m_Sensor, "CCD5710LS" );
+ strcpy( m_CameraModel, "57" );
+ m_CameraId = 18;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 536;
+ m_ImagingColumns = 512;
+ m_ClampColumns = 12;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 12;
+ m_TotalRows = 1056;
+ m_ImagingRows = 512;
+ m_UnderscanRows = 536;
+ m_OverscanRows = 8;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = true;
+ m_RowOffsetBinning = 536;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 0;
+ m_PixelSizeX = 13;
+ m_PixelSizeY = 13;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 1.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD5710LS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 23;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0006, 0x0006, 0x0006,
+ 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD5710LS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5710LS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5710LS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5710LS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5710LS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5710LS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD5710LS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD5710LS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD5710LS.h
new file mode 100644
index 00000000..546b5387
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD5710LS.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD5710LS.h: Interface file for the CApnCamData_CCD5710LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD5710LS : public CApnCamData
+{
+public:
+ CApnCamData_CCD5710LS();
+ virtual ~CApnCamData_CCD5710LS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD7700HS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD7700HS.cpp
new file mode 100644
index 00000000..7fdf2860
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD7700HS.cpp
@@ -0,0 +1,554 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD7700HS.cpp: Implementation file for the CApnCamData_CCD7700HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD7700HS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD7700HS::CApnCamData_CCD7700HS()
+{
+}
+
+
+CApnCamData_CCD7700HS::~CApnCamData_CCD7700HS()
+{
+}
+
+
+void CApnCamData_CCD7700HS::Initialize()
+{
+ strcpy( m_Sensor, "CCD7700HS" );
+ strcpy( m_CameraModel, "77" );
+ m_CameraId = 27;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 527;
+ m_ImagingColumns = 512;
+ m_ClampColumns = 15;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 0;
+ m_TotalRows = 512;
+ m_ImagingRows = 512;
+ m_UnderscanRows = 0;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 24;
+ m_PixelSizeY = 24;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD7700HS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 61;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x0008,
+ 0x0008, 0x0008, 0x000A, 0x000A, 0x000A, 0x000A, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
+ 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD7700HS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD7700HS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD7700HS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD7700HS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD7700HS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD7700HS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD7700HS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD7700HS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD7700HS.h
new file mode 100644
index 00000000..8ffb861e
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD7700HS.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD7700HS.h: Interface file for the CApnCamData_CCD7700HS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD7700HS : public CApnCamData
+{
+public:
+ CApnCamData_CCD7700HS();
+ virtual ~CApnCamData_CCD7700HS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD7700LS.cpp b/kstars/kstars/indi/apogee/ApnCamData_CCD7700LS.cpp
new file mode 100644
index 00000000..5e146a5d
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD7700LS.cpp
@@ -0,0 +1,554 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD7700LS.cpp: Implementation file for the CApnCamData_CCD7700LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_CCD7700LS.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_CCD7700LS::CApnCamData_CCD7700LS()
+{
+}
+
+
+CApnCamData_CCD7700LS::~CApnCamData_CCD7700LS()
+{
+}
+
+
+void CApnCamData_CCD7700LS::Initialize()
+{
+ strcpy( m_Sensor, "CCD7700LS" );
+ strcpy( m_CameraModel, "77" );
+ m_CameraId = 26;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 527;
+ m_ImagingColumns = 512;
+ m_ClampColumns = 15;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 0;
+ m_TotalRows = 512;
+ m_ImagingRows = 512;
+ m_UnderscanRows = 0;
+ m_OverscanRows = 0;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 24;
+ m_PixelSizeY = 24;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 300;
+ m_DefaultOffsetTwelveBit = 100;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_CCD7700LS::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 61;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x0008,
+ 0x0008, 0x0008, 0x000A, 0x000A, 0x000A, 0x000A, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
+ 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_CCD7700LS::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD7700LS::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 22;
+ const unsigned short SigNumElements = 8;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x0068, 0x006A, 0x006A, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0054, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD7700LS::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 48;
+ const unsigned short SigNumElements = 65;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x006C, 0x006C, 0x0068, 0x0068, 0x0068, 0x0068, 0x0068, 0x0078, 0x0078, 0x0078,
+ 0x0078, 0x0078, 0x0070, 0x0070, 0x0074, 0x0074, 0x0076, 0x0076, 0x0076, 0x0074,
+ 0x0074, 0x0074, 0x0074, 0x0074, 0x0074, 0x1074, 0x1074, 0x0074, 0x0074, 0x0074,
+ 0x00F4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x00D4,
+ 0x00D4, 0x00D4, 0x00D4, 0x00D4, 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0144, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x8104, 0x8104, 0x0004, 0x0004, 0x0004, 0x0004, 0x0404,
+ 0x0404, 0x0004, 0x0004, 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x0024, 0x0058, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x00D4, 0x00D4
+ },
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x004C, 0x004C, 0x004C, 0x004C, 0x004C,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0058, 0x0058, 0x0058, 0x0058,
+ 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0054, 0x0054, 0x0054, 0x0054, 0x0054,
+ 0x0054, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044
+ },
+ {
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD7700LS::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD7700LS::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0005, 0x0004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD7700LS::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0017
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x000C, 0x0008, 0x400A, 0x000A, 0x0008, 0x0008, 0x0218, 0x0018, 0x0018, 0x0018,
+ 0x0010, 0x0010, 0x0010, 0x0010, 0x0014, 0x2014, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x8005, 0x8004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_CCD7700LS::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_CCD7700LS.h b/kstars/kstars/indi/apogee/ApnCamData_CCD7700LS.h
new file mode 100644
index 00000000..423efe14
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_CCD7700LS.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_CCD7700LS.h: Interface file for the CApnCamData_CCD7700LS class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_CCD7700LS : public CApnCamData
+{
+public:
+ CApnCamData_CCD7700LS();
+ virtual ~CApnCamData_CCD7700LS();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF0261E.cpp b/kstars/kstars/indi/apogee/ApnCamData_KAF0261E.cpp
new file mode 100644
index 00000000..423f2eb4
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF0261E.cpp
@@ -0,0 +1,615 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF0261E.cpp: Implementation file for the CApnCamData_KAF0261E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_KAF0261E.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_KAF0261E::CApnCamData_KAF0261E()
+{
+}
+
+
+CApnCamData_KAF0261E::~CApnCamData_KAF0261E()
+{
+}
+
+
+void CApnCamData_KAF0261E::Initialize()
+{
+ strcpy( m_Sensor, "KAF0261E" );
+ strcpy( m_CameraModel, "260" );
+ m_CameraId = 2;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 530;
+ m_ImagingColumns = 512;
+ m_ClampColumns = 8;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 10;
+ m_TotalRows = 520;
+ m_ImagingRows = 512;
+ m_UnderscanRows = 4;
+ m_OverscanRows = 4;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 20;
+ m_PixelSizeY = 20;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 3;
+ m_MinSuggestedExpTime = 10.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 100;
+ m_DefaultOffsetTwelveBit = 255;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_KAF0261E::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 71;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
+ 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_KAF0261E::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 11;
+ const unsigned short SigNumElements = 12;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0004,
+ 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF0261E::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 24;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x0068, 0x1068, 0x1068, 0x1068, 0x1068, 0x1048,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0004, 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004,
+ 0x0404, 0x0004, 0x0005, 0x0064
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF0261E::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 27;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x8004, 0x8005, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x002A, 0x0052, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF0261E::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000B
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2008, 0x0004, 0x0004, 0x0004, 0x0005,
+ 0x4004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF0261E::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000C
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x2004, 0x0004, 0x0004,
+ 0x0005, 0x4004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF0261E::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000A, 0x0011, 0x0019, 0x0021, 0x0029, 0x0031, 0x0039, 0x0041, 0x0049, 0x0051
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF0261E::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF0261E.h b/kstars/kstars/indi/apogee/ApnCamData_KAF0261E.h
new file mode 100644
index 00000000..9aaefee7
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF0261E.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF0261E.h: Interface file for the CApnCamData_KAF0261E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_KAF0261E : public CApnCamData
+{
+public:
+ CApnCamData_KAF0261E();
+ virtual ~CApnCamData_KAF0261E();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF0401E.cpp b/kstars/kstars/indi/apogee/ApnCamData_KAF0401E.cpp
new file mode 100644
index 00000000..63e4d2f8
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF0401E.cpp
@@ -0,0 +1,615 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF0401E.cpp: Implementation file for the CApnCamData_KAF0401E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_KAF0401E.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_KAF0401E::CApnCamData_KAF0401E()
+{
+}
+
+
+CApnCamData_KAF0401E::~CApnCamData_KAF0401E()
+{
+}
+
+
+void CApnCamData_KAF0401E::Initialize()
+{
+ strcpy( m_Sensor, "KAF0401E" );
+ strcpy( m_CameraModel, "1" );
+ m_CameraId = 0;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 796;
+ m_ImagingColumns = 768;
+ m_ClampColumns = 14;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 14;
+ m_TotalRows = 520;
+ m_ImagingRows = 512;
+ m_UnderscanRows = 4;
+ m_OverscanRows = 4;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 9;
+ m_PixelSizeY = 9;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 1.5;
+ m_MinSuggestedExpTime = 10.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 100;
+ m_DefaultOffsetTwelveBit = 255;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_KAF0401E::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 71;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
+ 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_KAF0401E::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 11;
+ const unsigned short SigNumElements = 12;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0004,
+ 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF0401E::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 24;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x0068, 0x1068, 0x1068, 0x1068, 0x1068, 0x1048,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0004, 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004,
+ 0x0404, 0x0004, 0x0005, 0x0064
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF0401E::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 27;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x8004, 0x8005, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x002A, 0x0052, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF0401E::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000B
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2008, 0x0004, 0x0004, 0x0004, 0x0005,
+ 0x4004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF0401E::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000C
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x2004, 0x0004, 0x0004,
+ 0x0005, 0x4004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF0401E::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000A, 0x0011, 0x0019, 0x0021, 0x0029, 0x0031, 0x0039, 0x0041, 0x0049, 0x0051
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF0401E::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF0401E.h b/kstars/kstars/indi/apogee/ApnCamData_KAF0401E.h
new file mode 100644
index 00000000..5c947b9a
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF0401E.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF0401E.h: Interface file for the CApnCamData_KAF0401E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_KAF0401E : public CApnCamData
+{
+public:
+ CApnCamData_KAF0401E();
+ virtual ~CApnCamData_KAF0401E();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF1001E.cpp b/kstars/kstars/indi/apogee/ApnCamData_KAF1001E.cpp
new file mode 100644
index 00000000..6f58201d
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF1001E.cpp
@@ -0,0 +1,615 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF1001E.cpp: Implementation file for the CApnCamData_KAF1001E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_KAF1001E.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_KAF1001E::CApnCamData_KAF1001E()
+{
+}
+
+
+CApnCamData_KAF1001E::~CApnCamData_KAF1001E()
+{
+}
+
+
+void CApnCamData_KAF1001E::Initialize()
+{
+ strcpy( m_Sensor, "KAF1001E" );
+ strcpy( m_CameraModel, "6" );
+ m_CameraId = 5;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1044;
+ m_ImagingColumns = 1024;
+ m_ClampColumns = 8;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 12;
+ m_TotalRows = 1032;
+ m_ImagingRows = 1024;
+ m_UnderscanRows = 4;
+ m_OverscanRows = 4;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 24;
+ m_PixelSizeY = 24;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 3;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 100;
+ m_DefaultOffsetTwelveBit = 255;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_KAF1001E::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 71;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
+ 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_KAF1001E::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 11;
+ const unsigned short SigNumElements = 12;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0004,
+ 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1001E::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 24;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x0068, 0x1068, 0x1068, 0x1068, 0x1068, 0x1048,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0004, 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004,
+ 0x0404, 0x0004, 0x0005, 0x0064
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1001E::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 27;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x8004, 0x8005, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x002A, 0x0052, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1001E::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000B
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2008, 0x0004, 0x0004, 0x0004, 0x0005,
+ 0x4004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1001E::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000C
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x2004, 0x0004, 0x0004,
+ 0x0005, 0x4004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1001E::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000A, 0x0011, 0x0019, 0x0021, 0x0029, 0x0031, 0x0039, 0x0041, 0x0049, 0x0051
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1001E::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF1001E.h b/kstars/kstars/indi/apogee/ApnCamData_KAF1001E.h
new file mode 100644
index 00000000..2e23c278
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF1001E.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF1001E.h: Interface file for the CApnCamData_KAF1001E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_KAF1001E : public CApnCamData
+{
+public:
+ CApnCamData_KAF1001E();
+ virtual ~CApnCamData_KAF1001E();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF1301E.cpp b/kstars/kstars/indi/apogee/ApnCamData_KAF1301E.cpp
new file mode 100644
index 00000000..46d62d17
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF1301E.cpp
@@ -0,0 +1,615 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF1301E.cpp: Implementation file for the CApnCamData_KAF1301E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_KAF1301E.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_KAF1301E::CApnCamData_KAF1301E()
+{
+}
+
+
+CApnCamData_KAF1301E::~CApnCamData_KAF1301E()
+{
+}
+
+
+void CApnCamData_KAF1301E::Initialize()
+{
+ strcpy( m_Sensor, "KAF1301E" );
+ strcpy( m_CameraModel, "13" );
+ m_CameraId = 3;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1305;
+ m_ImagingColumns = 1280;
+ m_ClampColumns = 4;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 21;
+ m_TotalRows = 1028;
+ m_ImagingRows = 1024;
+ m_UnderscanRows = 2;
+ m_OverscanRows = 2;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 16;
+ m_PixelSizeY = 16;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 3;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 100;
+ m_DefaultOffsetTwelveBit = 255;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_KAF1301E::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 71;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
+ 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_KAF1301E::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 11;
+ const unsigned short SigNumElements = 12;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0004,
+ 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1301E::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 24;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x0068, 0x1068, 0x1068, 0x1068, 0x1068, 0x1048,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0004, 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004,
+ 0x0404, 0x0004, 0x0005, 0x0064
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1301E::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 27;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x8004, 0x8005, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x002A, 0x0052, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1301E::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000B
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2008, 0x0004, 0x0004, 0x0004, 0x0005,
+ 0x4004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1301E::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000C
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x2004, 0x0004, 0x0004,
+ 0x0005, 0x4004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1301E::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000A, 0x0011, 0x0019, 0x0021, 0x0029, 0x0031, 0x0039, 0x0041, 0x0049, 0x0051
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1301E::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF1301E.h b/kstars/kstars/indi/apogee/ApnCamData_KAF1301E.h
new file mode 100644
index 00000000..5ca47f78
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF1301E.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF1301E.h: Interface file for the CApnCamData_KAF1301E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_KAF1301E : public CApnCamData
+{
+public:
+ CApnCamData_KAF1301E();
+ virtual ~CApnCamData_KAF1301E();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF1401E.cpp b/kstars/kstars/indi/apogee/ApnCamData_KAF1401E.cpp
new file mode 100644
index 00000000..4c21d3bf
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF1401E.cpp
@@ -0,0 +1,615 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF1401E.cpp: Implementation file for the CApnCamData_KAF1401E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_KAF1401E.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_KAF1401E::CApnCamData_KAF1401E()
+{
+}
+
+
+CApnCamData_KAF1401E::~CApnCamData_KAF1401E()
+{
+}
+
+
+void CApnCamData_KAF1401E::Initialize()
+{
+ strcpy( m_Sensor, "KAF1401E" );
+ strcpy( m_CameraModel, "14" );
+ m_CameraId = 4;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1348;
+ m_ImagingColumns = 1320;
+ m_ClampColumns = 26;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 2;
+ m_TotalRows = 1037;
+ m_ImagingRows = 1035;
+ m_UnderscanRows = 1;
+ m_OverscanRows = 1;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 6.8;
+ m_PixelSizeY = 6.8;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 1;
+ m_MinSuggestedExpTime = 10.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 100;
+ m_DefaultOffsetTwelveBit = 255;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_KAF1401E::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 71;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
+ 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_KAF1401E::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 11;
+ const unsigned short SigNumElements = 12;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0004,
+ 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1401E::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 24;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x0068, 0x1068, 0x1068, 0x1068, 0x1068, 0x1048,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0004, 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004,
+ 0x0404, 0x0004, 0x0005, 0x0064
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1401E::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 27;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x8004, 0x8005, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x002A, 0x0052, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1401E::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000B
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2008, 0x0004, 0x0004, 0x0004, 0x0005,
+ 0x4004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1401E::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000C
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x2004, 0x0004, 0x0004,
+ 0x0005, 0x4004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1401E::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000A, 0x0011, 0x0019, 0x0021, 0x0029, 0x0031, 0x0039, 0x0041, 0x0049, 0x0051
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1401E::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF1401E.h b/kstars/kstars/indi/apogee/ApnCamData_KAF1401E.h
new file mode 100644
index 00000000..9ffedcec
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF1401E.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF1401E.h: Interface file for the CApnCamData_KAF1401E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_KAF1401E : public CApnCamData
+{
+public:
+ CApnCamData_KAF1401E();
+ virtual ~CApnCamData_KAF1401E();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF1602E.cpp b/kstars/kstars/indi/apogee/ApnCamData_KAF1602E.cpp
new file mode 100644
index 00000000..e46da326
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF1602E.cpp
@@ -0,0 +1,615 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF1602E.cpp: Implementation file for the CApnCamData_KAF1602E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_KAF1602E.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_KAF1602E::CApnCamData_KAF1602E()
+{
+}
+
+
+CApnCamData_KAF1602E::~CApnCamData_KAF1602E()
+{
+}
+
+
+void CApnCamData_KAF1602E::Initialize()
+{
+ strcpy( m_Sensor, "KAF1602E" );
+ strcpy( m_CameraModel, "2" );
+ m_CameraId = 1;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 1564;
+ m_ImagingColumns = 1536;
+ m_ClampColumns = 14;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 14;
+ m_TotalRows = 1032;
+ m_ImagingRows = 1024;
+ m_UnderscanRows = 4;
+ m_OverscanRows = 4;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 9;
+ m_PixelSizeY = 9;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 1.5;
+ m_MinSuggestedExpTime = 10.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 100;
+ m_DefaultOffsetTwelveBit = 255;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_KAF1602E::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 71;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
+ 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_KAF1602E::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 11;
+ const unsigned short SigNumElements = 12;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0004,
+ 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1602E::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 24;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x0068, 0x1068, 0x1068, 0x1068, 0x1068, 0x1048,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0004, 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004,
+ 0x0404, 0x0004, 0x0005, 0x0064
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1602E::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 27;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x8004, 0x8005, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x002A, 0x0052, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1602E::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000B
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2008, 0x0004, 0x0004, 0x0004, 0x0005,
+ 0x4004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1602E::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000C
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x2004, 0x0004, 0x0004,
+ 0x0005, 0x4004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1602E::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000A, 0x0011, 0x0019, 0x0021, 0x0029, 0x0031, 0x0039, 0x0041, 0x0049, 0x0051
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF1602E::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF1602E.h b/kstars/kstars/indi/apogee/ApnCamData_KAF1602E.h
new file mode 100644
index 00000000..c768852d
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF1602E.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF1602E.h: Interface file for the CApnCamData_KAF1602E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_KAF1602E : public CApnCamData
+{
+public:
+ CApnCamData_KAF1602E();
+ virtual ~CApnCamData_KAF1602E();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF16801E.cpp b/kstars/kstars/indi/apogee/ApnCamData_KAF16801E.cpp
new file mode 100644
index 00000000..19054ce3
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF16801E.cpp
@@ -0,0 +1,619 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF16801E.cpp: Implementation file for the CApnCamData_KAF16801E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_KAF16801E.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_KAF16801E::CApnCamData_KAF16801E()
+{
+}
+
+
+CApnCamData_KAF16801E::~CApnCamData_KAF16801E()
+{
+}
+
+
+void CApnCamData_KAF16801E::Initialize()
+{
+ strcpy( m_Sensor, "KAF16801E" );
+ strcpy( m_CameraModel, "16" );
+ m_CameraId = 9;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 4145;
+ m_ImagingColumns = 4098;
+ m_ClampColumns = 35;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 12;
+ m_TotalRows = 4128;
+ m_ImagingRows = 4098;
+ m_UnderscanRows = 10;
+ m_OverscanRows = 20;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 9;
+ m_PixelSizeY = 9;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 1.5;
+ m_MinSuggestedExpTime = 30.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 100;
+ m_DefaultOffsetTwelveBit = 255;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_KAF16801E::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 116;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0204, 0x0204, 0x0204, 0x0204, 0x0204, 0x0204, 0x0204, 0x0204, 0x0204,
+ 0x0204, 0x0004, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_KAF16801E::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x2;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 11;
+ const unsigned short SigNumElements = 12;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0004,
+ 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF16801E::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x2;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 24;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x0068, 0x1068, 0x1068, 0x1068, 0x1068, 0x1048,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0004, 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004,
+ 0x0404, 0x0004, 0x0005, 0x0064
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF16801E::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x2;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 27;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x8004, 0x8005, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x002A, 0x0052, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF16801E::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000B
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2008, 0x0004, 0x0004, 0x0004, 0x0005,
+ 0x4004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF16801E::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000C
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x2004, 0x0004, 0x0004,
+ 0x0005, 0x4004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF16801E::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000A, 0x0011, 0x0019, 0x0021, 0x0029, 0x0031, 0x0039, 0x0041, 0x0049, 0x0051
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF16801E::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF16801E.h b/kstars/kstars/indi/apogee/ApnCamData_KAF16801E.h
new file mode 100644
index 00000000..f46680a4
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF16801E.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF16801E.h: Interface file for the CApnCamData_KAF16801E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_KAF16801E : public CApnCamData
+{
+public:
+ CApnCamData_KAF16801E();
+ virtual ~CApnCamData_KAF16801E();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF3200E.cpp b/kstars/kstars/indi/apogee/ApnCamData_KAF3200E.cpp
new file mode 100644
index 00000000..e63e6899
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF3200E.cpp
@@ -0,0 +1,611 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF3200E.cpp: Implementation file for the CApnCamData_KAF3200E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_KAF3200E.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_KAF3200E::CApnCamData_KAF3200E()
+{
+}
+
+
+CApnCamData_KAF3200E::~CApnCamData_KAF3200E()
+{
+}
+
+
+void CApnCamData_KAF3200E::Initialize()
+{
+ strcpy( m_Sensor, "KAF3200E" );
+ strcpy( m_CameraModel, "32" );
+ m_CameraId = 6;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 2267;
+ m_ImagingColumns = 2184;
+ m_ClampColumns = 46;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 37;
+ m_TotalRows = 1510;
+ m_ImagingRows = 1472;
+ m_UnderscanRows = 34;
+ m_OverscanRows = 4;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 6.8;
+ m_PixelSizeY = 6.8;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 1;
+ m_MinSuggestedExpTime = 10.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 100;
+ m_DefaultOffsetTwelveBit = 255;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_KAF3200E::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 39;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0204, 0x0204, 0x0204, 0x0204, 0x0204, 0x0204, 0x0204, 0x0204, 0x0204,
+ 0x0204, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_KAF3200E::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x2;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 11;
+ const unsigned short SigNumElements = 12;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0004,
+ 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF3200E::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x2;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 24;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x0068, 0x1068, 0x1068, 0x1068, 0x1068, 0x1048,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0004, 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004,
+ 0x0404, 0x0004, 0x0005, 0x0064
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF3200E::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x2;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 27;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x8004, 0x8005, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x002A, 0x0052, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF3200E::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000B
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2008, 0x0004, 0x0004, 0x0004, 0x0005,
+ 0x4004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF3200E::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000C
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x2004, 0x0004, 0x0004,
+ 0x0005, 0x4004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF3200E::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000A, 0x0011, 0x0019, 0x0021, 0x0029, 0x0031, 0x0039, 0x0041, 0x0049, 0x0051
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF3200E::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF3200E.h b/kstars/kstars/indi/apogee/ApnCamData_KAF3200E.h
new file mode 100644
index 00000000..ee166530
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF3200E.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF3200E.h: Interface file for the CApnCamData_KAF3200E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_KAF3200E : public CApnCamData
+{
+public:
+ CApnCamData_KAF3200E();
+ virtual ~CApnCamData_KAF3200E();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF4202.cpp b/kstars/kstars/indi/apogee/ApnCamData_KAF4202.cpp
new file mode 100644
index 00000000..c9931294
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF4202.cpp
@@ -0,0 +1,615 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF4202.cpp: Implementation file for the CApnCamData_KAF4202 class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_KAF4202.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_KAF4202::CApnCamData_KAF4202()
+{
+}
+
+
+CApnCamData_KAF4202::~CApnCamData_KAF4202()
+{
+}
+
+
+void CApnCamData_KAF4202::Initialize()
+{
+ strcpy( m_Sensor, "KAF4202" );
+ strcpy( m_CameraModel, "4" );
+ m_CameraId = 7;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 2060;
+ m_ImagingColumns = 2032;
+ m_ClampColumns = 25;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 3;
+ m_TotalRows = 2048;
+ m_ImagingRows = 2044;
+ m_UnderscanRows = 2;
+ m_OverscanRows = 2;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 9;
+ m_PixelSizeY = 9;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 1.5;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 100;
+ m_DefaultOffsetTwelveBit = 255;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_KAF4202::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 71;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
+ 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_KAF4202::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 11;
+ const unsigned short SigNumElements = 12;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0004,
+ 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF4202::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 24;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x0068, 0x1068, 0x1068, 0x1068, 0x1068, 0x1048,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0004, 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004,
+ 0x0404, 0x0004, 0x0005, 0x0064
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF4202::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 27;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x8004, 0x8005, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x002A, 0x0052, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF4202::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000B
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2008, 0x0004, 0x0004, 0x0004, 0x0005,
+ 0x4004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF4202::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000C
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x2004, 0x0004, 0x0004,
+ 0x0005, 0x4004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF4202::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000A, 0x0011, 0x0019, 0x0021, 0x0029, 0x0031, 0x0039, 0x0041, 0x0049, 0x0051
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF4202::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF4202.h b/kstars/kstars/indi/apogee/ApnCamData_KAF4202.h
new file mode 100644
index 00000000..e34c51b0
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF4202.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF4202.h: Interface file for the CApnCamData_KAF4202 class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_KAF4202 : public CApnCamData
+{
+public:
+ CApnCamData_KAF4202();
+ virtual ~CApnCamData_KAF4202();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF6303E.cpp b/kstars/kstars/indi/apogee/ApnCamData_KAF6303E.cpp
new file mode 100644
index 00000000..cded741c
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF6303E.cpp
@@ -0,0 +1,615 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF6303E.cpp: Implementation file for the CApnCamData_KAF6303E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_KAF6303E.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_KAF6303E::CApnCamData_KAF6303E()
+{
+}
+
+
+CApnCamData_KAF6303E::~CApnCamData_KAF6303E()
+{
+}
+
+
+void CApnCamData_KAF6303E::Initialize()
+{
+ strcpy( m_Sensor, "KAF6303E" );
+ strcpy( m_CameraModel, "9" );
+ m_CameraId = 8;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 3100;
+ m_ImagingColumns = 3073;
+ m_ClampColumns = 15;
+ m_PreRoiSkipColumns = 0;
+ m_PostRoiSkipColumns = 0;
+ m_OverscanColumns = 12;
+ m_TotalRows = 2056;
+ m_ImagingRows = 2048;
+ m_UnderscanRows = 4;
+ m_OverscanRows = 4;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 9;
+ m_PixelSizeY = 9;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 1.5;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 100;
+ m_DefaultOffsetTwelveBit = 255;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_KAF6303E::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 71;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
+ 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_KAF6303E::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 11;
+ const unsigned short SigNumElements = 12;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0004,
+ 0x0005, 0x0004
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF6303E::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 24;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x0068, 0x1068, 0x1068, 0x1068, 0x1068, 0x1048,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8,
+ 0x10C8, 0x10C8, 0x10C8, 0x10C8, 0x10C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0004, 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004,
+ 0x0404, 0x0004, 0x0005, 0x0064
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF6303E::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0xE;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 27;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0064, 0x006A, 0x006A, 0x0068, 0x1068, 0x1068, 0x1068, 0x0068, 0x00E8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8,
+ 0x00C8, 0x00C8, 0x00C8, 0x00C8, 0x00C8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x8004, 0x8005, 0x0404
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x002A, 0x0052, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF6303E::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000B
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2008, 0x0004, 0x0004, 0x0004, 0x0005,
+ 0x4004
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF6303E::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000C
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x2004, 0x0004, 0x0004,
+ 0x0005, 0x4004
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF6303E::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000A, 0x0011, 0x0019, 0x0021, 0x0029, 0x0031, 0x0039, 0x0041, 0x0049, 0x0051
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_KAF6303E::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_KAF6303E.h b/kstars/kstars/indi/apogee/ApnCamData_KAF6303E.h
new file mode 100644
index 00000000..9b84a102
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_KAF6303E.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_KAF6303E.h: Interface file for the CApnCamData_KAF6303E class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_KAF6303E : public CApnCamData
+{
+public:
+ CApnCamData_KAF6303E();
+ virtual ~CApnCamData_KAF6303E();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamData_TH7899.cpp b/kstars/kstars/indi/apogee/ApnCamData_TH7899.cpp
new file mode 100644
index 00000000..69767c19
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_TH7899.cpp
@@ -0,0 +1,609 @@
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_TH7899.cpp: Implementation file for the CApnCamData_TH7899 class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData_TH7899.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+
+/////////////////////////////////////////////////////////////
+// Construction/Destruction
+/////////////////////////////////////////////////////////////
+
+
+CApnCamData_TH7899::CApnCamData_TH7899()
+{
+}
+
+
+CApnCamData_TH7899::~CApnCamData_TH7899()
+{
+}
+
+
+void CApnCamData_TH7899::Initialize()
+{
+ strcpy( m_Sensor, "TH7899" );
+ strcpy( m_CameraModel, "10" );
+ m_CameraId = 14;
+ m_InterlineCCD = false;
+ m_SupportsSerialA = true;
+ m_SupportsSerialB = true;
+ m_SensorTypeCCD = true;
+ m_TotalColumns = 2110;
+ m_ImagingColumns = 2048;
+ m_ClampColumns = 25;
+ m_PreRoiSkipColumns = 5;
+ m_PostRoiSkipColumns = 5;
+ m_OverscanColumns = 27;
+ m_TotalRows = 2054;
+ m_ImagingRows = 2048;
+ m_UnderscanRows = 3;
+ m_OverscanRows = 3;
+ m_VFlushBinning = 4;
+ m_EnableSingleRowOffset = false;
+ m_RowOffsetBinning = 1;
+ m_HFlushDisable = false;
+ m_ShutterCloseDelay = 20;
+ m_PixelSizeX = 14;
+ m_PixelSizeY = 14;
+ m_Color = false;
+ m_ReportedGainSixteenBit = 2;
+ m_MinSuggestedExpTime = 20.0;
+ m_CoolingSupported = true;
+ m_RegulatedCoolingSupported = true;
+ m_TempSetPoint = -20.0;
+ m_TempRampRateOne = 1000;
+ m_TempRampRateTwo = 2000;
+ m_TempBackoffPoint = 2.0;
+ m_DefaultGainTwelveBit = 100;
+ m_DefaultOffsetTwelveBit = 255;
+ m_DefaultRVoltage = 1000;
+
+ set_vpattern();
+
+ set_hpattern_clamp_sixteen();
+ set_hpattern_skip_sixteen();
+ set_hpattern_roi_sixteen();
+
+ set_hpattern_clamp_twelve();
+ set_hpattern_skip_twelve();
+ set_hpattern_roi_twelve();
+}
+
+
+void CApnCamData_TH7899::set_vpattern()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short NumElements = 18;
+ unsigned short Pattern[NumElements] =
+ {
+ 0x0000, 0x0018, 0x0018, 0x001A, 0x001A, 0x0012, 0x0012, 0x0016, 0x0016, 0x0006,
+ 0x0006, 0x000E, 0x000E, 0x000C, 0x000C, 0x0000, 0x0001, 0x0000
+ };
+
+ m_VerticalPattern.Mask = Mask;
+ m_VerticalPattern.NumElements = NumElements;
+ m_VerticalPattern.PatternData =
+ (unsigned short *)malloc(NumElements * sizeof(unsigned short));
+
+ for ( int i=0; i<NumElements; i++ )
+ {
+ m_VerticalPattern.PatternData[i] = Pattern[i];
+ }
+}
+
+
+void CApnCamData_TH7899::set_hpattern_skip_sixteen()
+{
+ const unsigned short Mask = 0x1E;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 11;
+ const unsigned short SigNumElements = 12;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0074, 0x007A, 0x007A, 0x0078, 0x1078, 0x1078, 0x1078, 0x0078, 0x00F8, 0x00D8,
+ 0x00D8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0004,
+ 0x0005, 0x0014
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0058, 0x0054
+ } };
+
+ set_hpattern( &m_SkipPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_TH7899::set_hpattern_clamp_sixteen()
+{
+ const unsigned short Mask = 0x1E;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 24;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0074, 0x007A, 0x007A, 0x0078, 0x0078, 0x1078, 0x1078, 0x1078, 0x1078, 0x1058,
+ 0x10D8, 0x10D8, 0x10D8, 0x10D8, 0x10D8, 0x10D8, 0x10D8, 0x10D8, 0x10D8, 0x10D8,
+ 0x10D8, 0x10D8, 0x10D8, 0x10D8, 0x10D8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0004, 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004,
+ 0x0404, 0x0004, 0x0005, 0x0074
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0058, 0x0054
+ } };
+
+ set_hpattern( &m_ClampPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_TH7899::set_hpattern_roi_sixteen()
+{
+ const unsigned short Mask = 0x1E;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 25;
+ const unsigned short SigNumElements = 27;
+
+ unsigned short RefPatternData[RefNumElements] =
+ {
+ 0x0074, 0x007A, 0x007A, 0x0078, 0x1078, 0x1078, 0x1078, 0x0078, 0x00F8, 0x00D8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D8,
+ 0x00D8, 0x00D8, 0x00D8, 0x00D8, 0x00D8
+ };
+
+ unsigned short SigPatternData[SigNumElements] =
+ {
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0144, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104,
+ 0x0104, 0x0104, 0x0104, 0x0104, 0x8004, 0x8005, 0x0414
+ };
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x0002, 0x002A, 0x0052, 0x007A, 0x00A2, 0x00CA, 0x00B6, 0x00C6, 0x00A2, 0x00B6
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0058, 0x0054
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0044, 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ },
+ {
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044, 0x0044,
+ 0x0044, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048, 0x0048,
+ 0x0048, 0x0044
+ } };
+
+ set_hpattern( &m_RoiPatternSixteen,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_TH7899::set_hpattern_skip_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000B
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0014, 0x021A, 0x0018, 0x0018, 0x0018, 0x2018, 0x0014, 0x0004, 0x0004, 0x0005,
+ 0x4014
+ } };
+
+ set_hpattern( &m_SkipPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_TH7899::set_hpattern_clamp_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 1;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000C
+ };
+
+ unsigned short BinPatternData[1][256] = {
+ {
+ 0x0014, 0x021A, 0x0018, 0x0018, 0x0018, 0x0018, 0x0014, 0x2004, 0x0004, 0x0004,
+ 0x0005, 0x4014
+ } };
+
+ set_hpattern( &m_ClampPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_TH7899::set_hpattern_roi_twelve()
+{
+ const unsigned short Mask = 0x0;
+ const unsigned short BinningLimit = 10;
+ const unsigned short RefNumElements = 0;
+ const unsigned short SigNumElements = 0;
+
+ unsigned short *RefPatternData = NULL;
+
+ unsigned short *SigPatternData = NULL;
+
+ unsigned short BinNumElements[APN_MAX_HBINNING] =
+ {
+ 0x000A, 0x0011, 0x0019, 0x0021, 0x0029, 0x0031, 0x0039, 0x0041, 0x0049, 0x0051
+ };
+
+ unsigned short BinPatternData[10][256] = {
+ {
+ 0x0014, 0x021A, 0x0018, 0x0018, 0x0018, 0x0014, 0x2004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0014, 0x021A, 0x0018, 0x0018, 0x0018, 0x2014, 0x0014, 0x0014, 0x0014, 0x0018,
+ 0x0018, 0x0018, 0x0018, 0x0014, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x8005, 0xC004
+ },
+ {
+ 0x0004, 0x020A, 0x0008, 0x0008, 0x0008, 0x2004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0004, 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0008, 0x0008, 0x0008, 0x0008, 0x0004, 0x0004, 0x8005,
+ 0xC004
+ } };
+
+ set_hpattern( &m_RoiPatternTwelve,
+ Mask,
+ BinningLimit,
+ RefNumElements,
+ SigNumElements,
+ BinNumElements,
+ RefPatternData,
+ SigPatternData,
+ BinPatternData );
+}
+
+
+void CApnCamData_TH7899::set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] )
+{
+ int i, j;
+
+ Pattern->Mask = Mask;
+ Pattern->BinningLimit = BinningLimit;
+ Pattern->RefNumElements = RefNumElements;
+ Pattern->SigNumElements = SigNumElements;
+
+ if ( RefNumElements > 0 )
+ {
+ Pattern->RefPatternData =
+ (unsigned short *)malloc(RefNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<RefNumElements; i++ )
+ {
+ Pattern->RefPatternData[i] = RefPatternData[i];
+ }
+ }
+
+ if ( SigNumElements > 0 )
+ {
+ Pattern->SigPatternData =
+ (unsigned short *)malloc(SigNumElements * sizeof(unsigned short));
+
+ for ( i=0; i<SigNumElements; i++ )
+ {
+ Pattern->SigPatternData[i] = SigPatternData[i];
+ }
+ }
+
+ if ( BinningLimit > 0 )
+ {
+ for ( i=0; i<BinningLimit; i++ )
+ {
+ Pattern->BinNumElements[i] = BinNumElements[i];
+
+ Pattern->BinPatternData[i] =
+ (unsigned short *)malloc(BinNumElements[i] * sizeof(unsigned short));
+
+ for ( j=0; j<BinNumElements[i]; j++ )
+ {
+ Pattern->BinPatternData[i][j] = BinPatternData[i][j];
+ }
+ }
+ }
+}
diff --git a/kstars/kstars/indi/apogee/ApnCamData_TH7899.h b/kstars/kstars/indi/apogee/ApnCamData_TH7899.h
new file mode 100644
index 00000000..296cc627
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamData_TH7899.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/////////////////////////////////////////////////////////////
+//
+// ApnCamData_TH7899.h: Interface file for the CApnCamData_TH7899 class.
+//
+/////////////////////////////////////////////////////////////
+
+#include "ApnCamData.h"
+
+class CApnCamData_TH7899 : public CApnCamData
+{
+public:
+ CApnCamData_TH7899();
+ virtual ~CApnCamData_TH7899();
+
+ void Initialize();
+
+private:
+
+ void set_vpattern();
+
+ void set_hpattern_clamp_sixteen();
+ void set_hpattern_skip_sixteen();
+ void set_hpattern_roi_sixteen();
+
+ void set_hpattern_clamp_twelve();
+ void set_hpattern_skip_twelve();
+ void set_hpattern_roi_twelve();
+
+ void set_hpattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short Mask,
+ unsigned short BinningLimit,
+ unsigned short RefNumElements,
+ unsigned short SigNumElements,
+ unsigned short BinNumElements[],
+ unsigned short RefPatternData[],
+ unsigned short SigPatternData[],
+ unsigned short BinPatternData[][APN_MAX_PATTERN_ENTRIES] );
+
+};
diff --git a/kstars/kstars/indi/apogee/ApnCamTable.cpp b/kstars/kstars/indi/apogee/ApnCamTable.cpp
new file mode 100644
index 00000000..5379ec9a
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamTable.cpp
@@ -0,0 +1,149 @@
+// ApnCamTable.cpp
+//
+// Copyright (c) 2003, 2004 Apogee Instruments, Inc.
+//////////////////////////////////////////////////////////////////////
+
+#include <string.h>
+
+#include "ApnCamTable.h"
+
+
+#define ALTA_MODEL_PREFIX "Alta-"
+
+
+void ApnCamModelLookup( unsigned short CamId, unsigned short Interface, char *szCamModel )
+{
+ char szModelNumber[20];
+ bool Error;
+
+ Error = false;
+
+ switch( CamId )
+ {
+ case APN_ALTA_KAF0401E_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAF0401E_CAM_SZ );
+ break;
+ case APN_ALTA_KAF1602E_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAF1602E_CAM_SZ );
+ break;
+ case APN_ALTA_KAF0261E_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAF0261E_CAM_SZ );
+ break;
+ case APN_ALTA_KAF1301E_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAF1301E_CAM_SZ );
+ break;
+ case APN_ALTA_KAF1401E_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAF1401E_CAM_SZ );
+ break;
+ case APN_ALTA_KAF1001E_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAF1001E_CAM_SZ );
+ break;
+ case APN_ALTA_KAF3200E_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAF3200E_CAM_SZ );
+ break;
+ case APN_ALTA_KAF4202_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAF4202_CAM_SZ );
+ break;
+ case APN_ALTA_KAF6303E_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAF6303E_CAM_SZ );
+ break;
+ case APN_ALTA_KAF16801E_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAF16801E_CAM_SZ );
+ break;
+ case APN_ALTA_CCD4710LS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD4710LS_CAM_SZ );
+ break;
+ case APN_ALTA_CCD4710HS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD4710HS_CAM_SZ );
+ break;
+ case APN_ALTA_TH7899_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_TH7899_CAM_SZ );
+ break;
+ case APN_ALTA_CCD4240LS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD4240LS_CAM_SZ );
+ break;
+ case APN_ALTA_CCD4240HS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD4240HS_CAM_SZ );
+ break;
+ case APN_ALTA_CCD5710LS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD5710LS_CAM_SZ );
+ break;
+ case APN_ALTA_CCD5710HS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD5710HS_CAM_SZ );
+ break;
+ case APN_ALTA_CCD3011LS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD3011LS_CAM_SZ );
+ break;
+ case APN_ALTA_CCD3011HS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD3011HS_CAM_SZ );
+ break;
+ case APN_ALTA_CCD5520LS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD5520LS_CAM_SZ );
+ break;
+ case APN_ALTA_CCD5520HS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD5520HS_CAM_SZ );
+ break;
+ case APN_ALTA_CCD4720LS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD4720LS_CAM_SZ );
+ break;
+ case APN_ALTA_CCD4720HS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD4720HS_CAM_SZ );
+ break;
+ case APN_ALTA_CCD7700LS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD7700LS_CAM_SZ );
+ break;
+ case APN_ALTA_CCD7700HS_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD7700HS_CAM_SZ );
+ break;
+ case APN_ALTA_KAI2001M_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAI2001M_CAM_SZ );
+ break;
+ case APN_ALTA_KAI2001MC_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAI2001MC_CAM_SZ );
+ break;
+ case APN_ALTA_KAI4020_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAI4020_CAM_SZ );
+ break;
+ case APN_ALTA_KAI11000_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAI11000_CAM_SZ );
+ break;
+ case APN_ALTA_KAI11000C_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_KAI11000C_CAM_SZ );
+ break;
+
+ case APN_ALTA_CCD4710LS2_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD4710LS2_CAM_SZ );
+ break;
+ case APN_ALTA_CCD4710LS3_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD4710LS3_CAM_SZ );
+ break;
+ case APN_ALTA_CCD4710LS4_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD4710LS4_CAM_SZ );
+ break;
+ case APN_ALTA_CCD4710LS5_CAM_ID:
+ strcpy( szModelNumber, APN_ALTA_CCD4710LS5_CAM_SZ );
+ break;
+ default:
+ Error = true;
+ break;
+ }
+
+ if ( Error )
+ {
+ strcpy( szCamModel, "Unknown" );
+ }
+ else
+ {
+ strcpy( szCamModel, ALTA_MODEL_PREFIX );
+
+ if ( Interface == 0 ) // Network Interface
+ strcat( szCamModel, "E" );
+
+ if ( Interface == 1 ) // USB 2.0 Interface
+ strcat( szCamModel, "U" );
+
+ strcat( szCamModel, szModelNumber );
+ }
+
+}
+
diff --git a/kstars/kstars/indi/apogee/ApnCamTable.h b/kstars/kstars/indi/apogee/ApnCamTable.h
new file mode 100644
index 00000000..8eb527c3
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamTable.h
@@ -0,0 +1,125 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __APN_CAM_TABLE_H__
+#define __APN_CAM_TABLE_H__
+
+
+#define APN_MODEL_COUNT 25 // total number of models
+
+
+#define APN_ALTA_KAF0401E_CAM_ID 0
+#define APN_ALTA_KAF0401E_CAM_SZ "1"
+
+#define APN_ALTA_KAF1602E_CAM_ID 1
+#define APN_ALTA_KAF1602E_CAM_SZ "2"
+
+#define APN_ALTA_KAF0261E_CAM_ID 2
+#define APN_ALTA_KAF0261E_CAM_SZ "260"
+
+#define APN_ALTA_KAF1301E_CAM_ID 3
+#define APN_ALTA_KAF1301E_CAM_SZ "13"
+
+#define APN_ALTA_KAF1401E_CAM_ID 4
+#define APN_ALTA_KAF1401E_CAM_SZ "14"
+
+#define APN_ALTA_KAF1001E_CAM_ID 5
+#define APN_ALTA_KAF1001E_CAM_SZ "6"
+
+#define APN_ALTA_KAF3200E_CAM_ID 6
+#define APN_ALTA_KAF3200E_CAM_SZ "32"
+
+#define APN_ALTA_KAF4202_CAM_ID 7
+#define APN_ALTA_KAF4202_CAM_SZ "4"
+
+#define APN_ALTA_KAF6303E_CAM_ID 8
+#define APN_ALTA_KAF6303E_CAM_SZ "9"
+
+#define APN_ALTA_KAF16801E_CAM_ID 9
+#define APN_ALTA_KAF16801E_CAM_SZ "16"
+
+#define APN_ALTA_CCD4710LS_CAM_ID 10
+#define APN_ALTA_CCD4710LS_CAM_SZ "47"
+
+#define APN_ALTA_CCD4710HS_CAM_ID 11
+#define APN_ALTA_CCD4710HS_CAM_SZ "47"
+
+#define APN_ALTA_TH7899_CAM_ID 14
+#define APN_ALTA_TH7899_CAM_SZ "10"
+
+#define APN_ALTA_CCD4240LS_CAM_ID 16
+#define APN_ALTA_CCD4240LS_CAM_SZ "42"
+
+#define APN_ALTA_CCD4240HS_CAM_ID 17
+#define APN_ALTA_CCD4240HS_CAM_SZ "42"
+
+#define APN_ALTA_CCD5710LS_CAM_ID 18
+#define APN_ALTA_CCD5710LS_CAM_SZ "57"
+
+#define APN_ALTA_CCD5710HS_CAM_ID 19
+#define APN_ALTA_CCD5710HS_CAM_SZ "57"
+
+#define APN_ALTA_CCD3011LS_CAM_ID 20
+#define APN_ALTA_CCD3011LS_CAM_SZ "30"
+
+#define APN_ALTA_CCD3011HS_CAM_ID 21
+#define APN_ALTA_CCD3011HS_CAM_SZ "30"
+
+#define APN_ALTA_CCD5520LS_CAM_ID 22
+#define APN_ALTA_CCD5520LS_CAM_SZ "55"
+
+#define APN_ALTA_CCD5520HS_CAM_ID 23
+#define APN_ALTA_CCD5520HS_CAM_SZ "55"
+
+#define APN_ALTA_CCD4720LS_CAM_ID 24
+#define APN_ALTA_CCD4720LS_CAM_SZ "4720"
+
+#define APN_ALTA_CCD4720HS_CAM_ID 25
+#define APN_ALTA_CCD4720HS_CAM_SZ "4720"
+
+#define APN_ALTA_CCD7700LS_CAM_ID 26
+#define APN_ALTA_CCD7700LS_CAM_SZ "77"
+
+#define APN_ALTA_CCD7700HS_CAM_ID 27
+#define APN_ALTA_CCD7700HS_CAM_SZ "77"
+
+#define APN_ALTA_KAI2001M_CAM_ID 64
+#define APN_ALTA_KAI2001M_CAM_SZ "2000"
+
+#define APN_ALTA_KAI2001MC_CAM_ID 65
+#define APN_ALTA_KAI2001MC_CAM_SZ "2000C"
+
+#define APN_ALTA_KAI4020_CAM_ID 66
+#define APN_ALTA_KAI4020_CAM_SZ "4000"
+
+#define APN_ALTA_KAI11000_CAM_ID 67
+#define APN_ALTA_KAI11000_CAM_SZ "11000"
+
+#define APN_ALTA_KAI11000C_CAM_ID 68
+#define APN_ALTA_KAI11000C_CAM_SZ "11000C"
+
+#define APN_ALTA_CCD4710LS2_CAM_ID 12
+#define APN_ALTA_CCD4710LS2_CAM_SZ "4710"
+
+#define APN_ALTA_CCD4710LS3_CAM_ID 13
+#define APN_ALTA_CCD4710LS3_CAM_SZ "4710"
+
+#define APN_ALTA_CCD4710LS4_CAM_ID 15
+#define APN_ALTA_CCD4710LS4_CAM_SZ "4710"
+
+#define APN_ALTA_CCD4710LS5_CAM_ID 28
+#define APN_ALTA_CCD4710LS5_CAM_SZ "4710"
+
+
+// Helper function prototype
+
+void ApnCamModelLookup( unsigned short CamId, unsigned short Interface, char *szCamModel );
+
+
+#endif
diff --git a/kstars/kstars/indi/apogee/ApnCamera.cpp b/kstars/kstars/indi/apogee/ApnCamera.cpp
new file mode 100644
index 00000000..4e8c1b00
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamera.cpp
@@ -0,0 +1,1890 @@
+// ApnCamera.cpp: implementation of the CApnCamera class.
+//
+// Copyright (c) 2003, 2004 Apogee Instruments, Inc.
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+
+#include "ApnCamera.h"
+#include "ApnCamTable.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CApnCamera::CApnCamera()
+{
+ m_ApnSensorInfo = NULL;
+}
+
+CApnCamera::~CApnCamera()
+{
+ if ( m_ApnSensorInfo != NULL )
+ {
+ delete m_ApnSensorInfo;
+ m_ApnSensorInfo = NULL;
+ }
+ CloseDriver();
+}
+
+bool CApnCamera::Expose( double Duration, bool Light )
+{
+ ULONG ExpTime;
+ unsigned short BitsPerPixel(0);
+ unsigned short UnbinnedRoiX;
+ unsigned short UnbinnedRoiY;
+ unsigned short PreRoiSkip, PostRoiSkip;
+ unsigned short PreRoiRows, PostRoiRows;
+ unsigned short PreRoiVBinning, PostRoiVBinning;
+
+ unsigned short RoiRegBuffer[12];
+ unsigned short RoiRegData[12];
+
+ unsigned short TotalHPixels;
+ unsigned short TotalVPixels;
+
+
+ while ( read_ImagingStatus() != Apn_Status_Flushing )
+ {
+ Sleep( 20 );
+ }
+
+ // Validate the "Duration" parameter
+ if ( Duration < APN_EXPOSURE_TIME_MIN )
+ Duration = APN_EXPOSURE_TIME_MIN;
+
+ // Validate the ROI params
+ UnbinnedRoiX = m_RoiPixelsH * m_RoiBinningH;
+
+ PreRoiSkip = m_RoiStartX;
+
+ PostRoiSkip = m_ApnSensorInfo->m_TotalColumns -
+ m_ApnSensorInfo->m_ClampColumns -
+ PreRoiSkip -
+ UnbinnedRoiX;
+
+ TotalHPixels = UnbinnedRoiX + PreRoiSkip + PostRoiSkip + m_ApnSensorInfo->m_ClampColumns;
+
+ if ( TotalHPixels != m_ApnSensorInfo->m_TotalColumns )
+ return false;
+
+ UnbinnedRoiY = m_RoiPixelsV * m_RoiBinningV;
+
+ PreRoiRows = m_ApnSensorInfo->m_UnderscanRows +
+ m_RoiStartY;
+
+ PostRoiRows = m_ApnSensorInfo->m_TotalRows -
+ PreRoiRows -
+ UnbinnedRoiY;
+
+ TotalVPixels = UnbinnedRoiY + PreRoiRows + PostRoiRows;
+
+ if ( TotalVPixels != m_ApnSensorInfo->m_TotalRows )
+ return false;
+
+ // Calculate the exposure time to program to the camera
+ ExpTime = ((unsigned long)(Duration / APN_TIMER_RESOLUTION)) + APN_TIMER_OFFSET_COUNT;
+
+ Write( FPGA_REG_TIMER_LOWER, (unsigned short)(ExpTime & 0xFFFF));
+ ExpTime = ExpTime >> 16;
+ Write( FPGA_REG_TIMER_UPPER, (unsigned short)(ExpTime & 0xFFFF));
+
+ m_pvtExposurePixelsV = m_RoiPixelsV;
+ m_pvtExposurePixelsH = m_RoiPixelsH;
+
+ if ( m_DataBits == Apn_Resolution_SixteenBit )
+ {
+ BitsPerPixel = 16;
+ }
+ else if ( m_DataBits == Apn_Resolution_TwelveBit )
+ {
+ BitsPerPixel = 12;
+ }
+
+ if ( PreStartExpose( BitsPerPixel ) != 0 )
+ {
+ return false;
+ }
+
+ // Calculate the vertical parameters
+ PreRoiVBinning = m_ApnSensorInfo->m_RowOffsetBinning;
+
+ PostRoiVBinning = 1;
+
+ // For interline CCDs, set "Fast Dump" mode if the particular array is NOT digitized
+ if ( m_ApnSensorInfo->m_InterlineCCD )
+ {
+ // use the fast dump feature to get rid of the data quickly.
+ // one row, binning to the original row count
+ // note that we only are not digitized in arrays 1 and 3
+ PreRoiVBinning = PreRoiRows;
+ PostRoiVBinning = PostRoiRows;
+
+ PreRoiVBinning |= FPGA_BIT_ARRAY_FASTDUMP;
+ PostRoiVBinning |= FPGA_BIT_ARRAY_FASTDUMP;
+
+ PreRoiRows = 1;
+ PostRoiRows = 1;
+ }
+
+ // Set up the geometry for a full frame device
+ if ( m_ApnSensorInfo->m_EnableSingleRowOffset )
+ {
+ PreRoiVBinning += PreRoiRows;
+ PostRoiVBinning = PostRoiRows;
+
+ PreRoiVBinning |= FPGA_BIT_ARRAY_FASTDUMP;
+ PostRoiVBinning |= FPGA_BIT_ARRAY_FASTDUMP;
+
+ PreRoiRows = 1;
+ PostRoiRows = 1;
+ }
+
+
+ // Issue the reset
+ RoiRegBuffer[0] = FPGA_REG_COMMAND_B;
+ RoiRegData[0] = FPGA_BIT_CMD_RESET;
+
+ // Program the horizontal settings
+ RoiRegBuffer[1] = FPGA_REG_PREROI_SKIP_COUNT;
+ RoiRegData[1] = PreRoiSkip;
+
+ RoiRegBuffer[2] = FPGA_REG_ROI_COUNT;
+ // Number of ROI pixels. Adjust the 12bit operation here to account for an extra
+ // 10 pixel shift as a result of the A/D conversion.
+ if ( m_DataBits == Apn_Resolution_SixteenBit )
+ {
+ RoiRegData[2] = m_pvtExposurePixelsH + 1;
+ }
+ else if ( m_DataBits == Apn_Resolution_TwelveBit )
+ {
+ RoiRegData[2] = m_pvtExposurePixelsH + 10;
+ }
+
+ RoiRegBuffer[3] = FPGA_REG_POSTROI_SKIP_COUNT;
+ RoiRegData[3] = PostRoiSkip;
+
+ // Program the vertical settings
+ RoiRegBuffer[4] = FPGA_REG_A1_ROW_COUNT;
+ RoiRegData[4] = PreRoiRows;
+ RoiRegBuffer[5] = FPGA_REG_A1_VBINNING;
+ RoiRegData[5] = PreRoiVBinning;
+
+ RoiRegBuffer[6] = FPGA_REG_A2_ROW_COUNT;
+ RoiRegData[6] = m_RoiPixelsV;
+ RoiRegBuffer[7] = FPGA_REG_A2_VBINNING;
+ RoiRegData[7] = (m_RoiBinningV | FPGA_BIT_ARRAY_DIGITIZE);
+
+ RoiRegBuffer[8] = FPGA_REG_A3_ROW_COUNT;
+ RoiRegData[8] = PostRoiRows;
+ RoiRegBuffer[9] = FPGA_REG_A3_VBINNING;
+ RoiRegData[9] = PostRoiVBinning;
+
+ // Issue the reset
+ RoiRegBuffer[10] = FPGA_REG_COMMAND_B;
+ RoiRegData[10] = FPGA_BIT_CMD_RESET;
+
+ switch ( m_pvtCameraMode )
+ {
+ case Apn_CameraMode_Normal:
+ if ( Light )
+ {
+ RoiRegBuffer[11] = FPGA_REG_COMMAND_A;
+ RoiRegData[11] = FPGA_BIT_CMD_EXPOSE;
+ }
+ else
+ {
+ RoiRegBuffer[11] = FPGA_REG_COMMAND_A;
+ RoiRegData[11] = FPGA_BIT_CMD_DARK;
+ }
+ break;
+ case Apn_CameraMode_TDI:
+ RoiRegBuffer[11] = FPGA_REG_COMMAND_A;
+ RoiRegData[11] = FPGA_BIT_CMD_TDI;
+ break;
+ case Apn_CameraMode_Test:
+ if ( Light )
+ {
+ RoiRegBuffer[11] = FPGA_REG_COMMAND_A;
+ RoiRegData[11] = FPGA_BIT_CMD_EXPOSE;
+ }
+ else
+ {
+ RoiRegBuffer[11] = FPGA_REG_COMMAND_A;
+ RoiRegData[11] = FPGA_BIT_CMD_DARK;
+ }
+ break;
+ case Apn_CameraMode_ExternalTrigger:
+ RoiRegBuffer[11] = FPGA_REG_COMMAND_A;
+ RoiRegData[11] = FPGA_BIT_CMD_TRIGGER_EXPOSE;
+ break;
+ case Apn_CameraMode_ExternalShutter:
+ break;
+ }
+
+ // Send the instruction sequence to the camera
+ WriteMultiMRMD( RoiRegBuffer, RoiRegData, 12 );
+
+ m_pvtImageInProgress = true;
+ m_pvtImageReady = false;
+
+ return true;
+}
+
+bool CApnCamera::ResetSystem()
+{
+ // Reset the camera engine
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_RESET );
+
+ // Start flushing
+ Write( FPGA_REG_COMMAND_A, FPGA_BIT_CMD_FLUSH );
+
+ return true;
+}
+
+bool CApnCamera::PauseTimer( bool PauseState )
+{
+ unsigned short RegVal;
+ bool CurrentState;
+
+ Read( FPGA_REG_OP_A, RegVal );
+
+ CurrentState = ( RegVal & FPGA_BIT_PAUSE_TIMER ) == FPGA_BIT_PAUSE_TIMER;
+
+ if ( CurrentState != PauseState )
+ {
+ if ( PauseState )
+ {
+ RegVal |= FPGA_BIT_PAUSE_TIMER;
+ }
+ else
+ {
+ RegVal &= ~FPGA_BIT_PAUSE_TIMER;
+ }
+ Write ( FPGA_REG_OP_A, RegVal );
+ }
+
+ return true;
+}
+
+bool CApnCamera::StopExposure( bool DigitizeData )
+{
+ if ( m_pvtImageInProgress )
+ {
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_END_EXPOSURE );
+
+ if ( PostStopExposure( DigitizeData ) != 0 )
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+unsigned short CApnCamera::GetExposurePixelsH()
+{
+ return m_pvtExposurePixelsH;
+}
+
+unsigned short CApnCamera::GetExposurePixelsV()
+{
+ return m_pvtExposurePixelsV;
+}
+
+double CApnCamera::read_InputVoltage()
+{
+ UpdateGeneralStatus();
+
+ return m_pvtInputVoltage;
+}
+
+long CApnCamera::read_AvailableMemory()
+{
+ long AvailableMemory(0);
+
+ switch( m_CameraInterface )
+ {
+ case Apn_Interface_NET:
+ AvailableMemory = 28 * 1024;
+ break;
+ case Apn_Interface_USB:
+ AvailableMemory = 32 * 1024;
+ break;
+ default:
+ break;
+ }
+
+ return AvailableMemory;
+}
+
+unsigned short CApnCamera::read_FirmwareVersion()
+{
+ unsigned short FirmwareVersion;
+ Read( FPGA_REG_FIRMWARE_REV, FirmwareVersion );
+ return FirmwareVersion;
+}
+
+bool CApnCamera::read_ShutterState()
+{
+ UpdateGeneralStatus();
+
+ return m_pvtShutterState;
+}
+
+bool CApnCamera::read_DisableShutter()
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_OP_A, RegVal );
+ return ( (RegVal & FPGA_BIT_DISABLE_SHUTTER) != 0 );
+}
+
+void CApnCamera::write_DisableShutter( bool DisableShutter )
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_OP_A, RegVal );
+
+ if ( DisableShutter )
+ RegVal |= FPGA_BIT_DISABLE_SHUTTER;
+ else
+ RegVal &= ~FPGA_BIT_DISABLE_SHUTTER;
+
+ Write( FPGA_REG_OP_A, RegVal );
+}
+
+bool CApnCamera::read_ForceShutterOpen()
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_OP_A, RegVal );
+ return ( (RegVal & FPGA_BIT_FORCE_SHUTTER) != 0 );
+}
+
+void CApnCamera::write_ForceShutterOpen( bool ForceShutterOpen )
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_OP_A, RegVal );
+
+ if ( ForceShutterOpen )
+ RegVal |= FPGA_BIT_FORCE_SHUTTER;
+ else
+ RegVal &= ~FPGA_BIT_FORCE_SHUTTER;
+
+ Write( FPGA_REG_OP_A, RegVal );
+}
+
+bool CApnCamera::read_ShutterAmpControl()
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_OP_A, RegVal );
+ return ( (RegVal & FPGA_BIT_SHUTTER_AMP_CONTROL ) != 0 );
+}
+
+void CApnCamera::write_ShutterAmpControl( bool ShutterAmpControl )
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_OP_A, RegVal );
+
+ if ( ShutterAmpControl )
+ RegVal |= FPGA_BIT_SHUTTER_AMP_CONTROL;
+ else
+ RegVal &= ~FPGA_BIT_SHUTTER_AMP_CONTROL;
+
+ Write( FPGA_REG_OP_A, RegVal );
+}
+
+bool CApnCamera::read_ExternalIoReadout()
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_OP_A, RegVal );
+ return ( (RegVal & FPGA_BIT_SHUTTER_MODE) != 0 );
+}
+
+void CApnCamera::write_ExternalIoReadout( bool ExternalIoReadout )
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_OP_A, RegVal );
+
+ if ( ExternalIoReadout )
+ RegVal |= FPGA_BIT_SHUTTER_MODE;
+ else
+ RegVal &= ~FPGA_BIT_SHUTTER_MODE;
+
+ Write( FPGA_REG_OP_A, RegVal );
+}
+
+bool CApnCamera::read_FastSequence()
+{
+ if ( m_ApnSensorInfo->m_InterlineCCD == false )
+ return false;
+
+ unsigned short RegVal;
+ Read( FPGA_REG_OP_A, RegVal );
+ return ( (RegVal & FPGA_BIT_RATIO) != 0 );
+}
+
+void CApnCamera::write_FastSequence( bool FastSequence )
+{
+ if ( m_ApnSensorInfo->m_InterlineCCD == false )
+ return;
+
+ unsigned short RegVal;
+ Read( FPGA_REG_OP_A, RegVal );
+
+ if ( FastSequence )
+ {
+ RegVal |= FPGA_BIT_RATIO;
+ Write( FPGA_REG_SHUTTER_CLOSE_DELAY, 0x0 );
+ }
+ else
+ {
+ RegVal &= ~FPGA_BIT_RATIO;
+ }
+
+ Write( FPGA_REG_OP_A, RegVal );
+}
+
+Apn_NetworkMode CApnCamera::read_NetworkTransferMode()
+{
+ return m_pvtNetworkTransferMode;
+}
+
+void CApnCamera::write_NetworkTransferMode( Apn_NetworkMode TransferMode )
+{
+ SetNetworkTransferMode( TransferMode );
+
+ m_pvtNetworkTransferMode = TransferMode;
+}
+
+Apn_CameraMode CApnCamera::read_CameraMode()
+{
+ return m_pvtCameraMode;
+}
+
+void CApnCamera::write_CameraMode( Apn_CameraMode CameraMode )
+{
+ unsigned short RegVal;
+
+
+ // If our state isn't going to change, do nothing
+ if ( m_pvtCameraMode == CameraMode )
+ return;
+
+ // If we didn't return already, then if we know our state is going to
+ // change. If we're in test mode, clear the appropriate FPGA bit(s).
+ switch( m_pvtCameraMode )
+ {
+ case Apn_CameraMode_Normal:
+ break;
+ case Apn_CameraMode_TDI:
+ break;
+ case Apn_CameraMode_Test:
+ Read( FPGA_REG_OP_B, RegVal );
+ RegVal &= ~FPGA_BIT_AD_SIMULATION;
+ Write( FPGA_REG_OP_B, RegVal );
+ break;
+ case Apn_CameraMode_ExternalTrigger:
+ break;
+ case Apn_CameraMode_ExternalShutter:
+ Read( FPGA_REG_OP_A, RegVal );
+ RegVal &= ~FPGA_BIT_SHUTTER_SOURCE;
+ Write( FPGA_REG_OP_A, RegVal );
+ break;
+ }
+
+ switch ( CameraMode )
+ {
+ case Apn_CameraMode_Normal:
+ break;
+ case Apn_CameraMode_TDI:
+ break;
+ case Apn_CameraMode_Test:
+ Read( FPGA_REG_OP_B, RegVal );
+ RegVal |= FPGA_BIT_AD_SIMULATION;
+ Write( FPGA_REG_OP_B, RegVal );
+ break;
+ case Apn_CameraMode_ExternalTrigger:
+ Read( FPGA_REG_IO_PORT_ASSIGNMENT, RegVal );
+ RegVal |= 0x01;
+ Write( FPGA_REG_IO_PORT_ASSIGNMENT, RegVal );
+ break;
+ case Apn_CameraMode_ExternalShutter:
+ Read( FPGA_REG_OP_A, RegVal );
+ RegVal |= FPGA_BIT_SHUTTER_SOURCE;
+ Write( FPGA_REG_OP_A, RegVal );
+ break;
+ }
+
+ m_pvtCameraMode = CameraMode;
+}
+
+void CApnCamera::write_DataBits( Apn_Resolution BitResolution )
+{
+ unsigned short RegVal;
+
+ if ( m_CameraInterface == Apn_Interface_NET )
+ {
+ // The network interface is 16bpp only. Changing the resolution
+ // for network cameras has no effect.
+ return;
+ }
+
+ if ( m_DataBits != BitResolution )
+ {
+ // Reset the camera
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_RESET );
+
+ // Change bit setting after the reset
+ Read( FPGA_REG_OP_A, RegVal );
+
+ if ( BitResolution == Apn_Resolution_TwelveBit )
+ RegVal |= FPGA_BIT_DIGITIZATION_RES;
+
+ if ( BitResolution == Apn_Resolution_SixteenBit )
+ RegVal &= ~FPGA_BIT_DIGITIZATION_RES;
+
+ Write( FPGA_REG_OP_A, RegVal );
+
+ m_DataBits = BitResolution;
+
+ LoadClampPattern();
+ LoadSkipPattern();
+ LoadRoiPattern( m_RoiBinningH );
+
+ // Reset the camera
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_RESET );
+ // Start flushing
+ Write( FPGA_REG_COMMAND_A, FPGA_BIT_CMD_FLUSH );
+ }
+}
+
+Apn_Status CApnCamera::read_ImagingStatus()
+{
+ bool Exposing, Active, Done, Flushing, WaitOnTrigger;
+ bool DataHalted, RamError;
+
+
+ UpdateGeneralStatus();
+
+ // Update the ImagingStatus
+ Exposing = false;
+ Active = false;
+ Done = false;
+ Flushing = false;
+ WaitOnTrigger = false;
+ DataHalted = false;
+ RamError = false;
+
+ if ( (m_pvtStatusReg & FPGA_BIT_STATUS_IMAGING_ACTIVE) != 0 )
+ Active = true;
+
+ if ( (m_pvtStatusReg & FPGA_BIT_STATUS_IMAGE_EXPOSING) != 0 )
+ Exposing = true;
+
+ if ( (m_pvtStatusReg & FPGA_BIT_STATUS_IMAGE_DONE) != 0 )
+ Done = true;
+
+ if ( (m_pvtStatusReg & FPGA_BIT_STATUS_FLUSHING) != 0 )
+ Flushing = true;
+
+ if ( (m_pvtStatusReg & FPGA_BIT_STATUS_WAITING_TRIGGER) != 0 )
+ WaitOnTrigger = true;
+
+ if ( (m_pvtStatusReg & FPGA_BIT_STATUS_DATA_HALTED) != 0 )
+ DataHalted = true;
+
+ if ( (m_pvtStatusReg & FPGA_BIT_STATUS_PATTERN_ERROR) != 0 )
+ RamError = true;
+
+ if ( RamError )
+ {
+ m_pvtImagingStatus = Apn_Status_PatternError;
+ }
+ else
+ {
+ if ( DataHalted )
+ {
+ m_pvtImagingStatus = Apn_Status_DataError;
+ }
+ else
+ {
+ if ( WaitOnTrigger )
+ {
+ m_pvtImagingStatus = Apn_Status_WaitingOnTrigger;
+ }
+ else
+ {
+ if ( Done && m_pvtImageInProgress )
+ {
+ m_pvtImageReady = true;
+ m_pvtImagingStatus = Apn_Status_ImageReady;
+ }
+ else
+ {
+ if ( Active )
+ {
+ if ( Exposing )
+ m_pvtImagingStatus = Apn_Status_Exposing;
+ else
+ m_pvtImagingStatus = Apn_Status_ImagingActive;
+ }
+ else
+ {
+ if ( Flushing )
+ m_pvtImagingStatus = Apn_Status_Flushing;
+ else
+ m_pvtImagingStatus = Apn_Status_Idle;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ switch( m_pvtImagingStatus )
+ {
+ case Apn_Status_DataError:
+ OutputDebugString( "ImagingStatus: Apn_Status_DataError" );
+ break;
+ case Apn_Status_PatternError:
+ OutputDebugString( "ImagingStatus: Apn_Status_PatternError" );
+ break;
+ case Apn_Status_Idle:
+ OutputDebugString( "ImagingStatus: Apn_Status_Idle" );
+ break;
+ case Apn_Status_Exposing:
+ OutputDebugString( "ImagingStatus: Apn_Status_Exposing" );
+ break;
+ case Apn_Status_ImagingActive:
+ OutputDebugString( "ImagingStatus: Apn_Status_ImagingActive" );
+ break;
+ case Apn_Status_ImageReady:
+ OutputDebugString( "ImagingStatus: Apn_Status_ImageReady" );
+ break;
+ case Apn_Status_Flushing:
+ OutputDebugString( "ImagingStatus: Apn_Status_Flushing" );
+ break;
+ case Apn_Status_WaitingOnTrigger:
+ OutputDebugString( "ImagingStatus: Apn_Status_WaitingOnTrigger" );
+ break;
+ default:
+ OutputDebugString( "ImagingStatus: UNDEFINED!!" );
+ break;
+ }
+ */
+
+ return m_pvtImagingStatus;
+}
+
+Apn_LedMode CApnCamera::read_LedMode()
+{
+ return m_pvtLedMode;
+}
+
+void CApnCamera::write_LedMode( Apn_LedMode LedMode )
+{
+ unsigned short RegVal;
+
+ Read( FPGA_REG_OP_A, RegVal );
+
+ switch ( LedMode )
+ {
+ case Apn_LedMode_DisableAll:
+ RegVal |= FPGA_BIT_LED_DISABLE;
+ break;
+ case Apn_LedMode_DisableWhileExpose:
+ RegVal &= ~FPGA_BIT_LED_DISABLE;
+ RegVal |= FPGA_BIT_LED_EXPOSE_DISABLE;
+ break;
+ case Apn_LedMode_EnableAll:
+ RegVal &= ~FPGA_BIT_LED_DISABLE;
+ RegVal &= ~FPGA_BIT_LED_EXPOSE_DISABLE;
+ break;
+ }
+
+ m_pvtLedMode = LedMode;
+
+ Write( FPGA_REG_OP_A, RegVal );
+}
+
+Apn_LedState CApnCamera::read_LedState( unsigned short LedId )
+{
+ Apn_LedState RetVal(0);
+
+ if ( LedId == 0 ) // LED A
+ RetVal = m_pvtLedStateA;
+
+ if ( LedId == 1 ) // LED B
+ RetVal = m_pvtLedStateB;
+
+ return RetVal;
+}
+
+void CApnCamera::write_LedState( unsigned short LedId, Apn_LedState LedState )
+{
+ unsigned short RegVal;
+
+
+ RegVal = 0x0;
+
+ if ( LedId == 0 ) // LED A
+ {
+ RegVal = (m_pvtLedStateB << 4); // keep the current settings for LED B
+ RegVal |= LedState; // program new settings
+ m_pvtLedStateA = LedState;
+ }
+ else if ( LedId == 1 ) // LED B
+ {
+ RegVal = m_pvtLedStateA; // keep the current settings for LED A
+ RegVal |= (LedState << 4); // program new settings
+ m_pvtLedStateB = LedState;
+ }
+
+ Write( FPGA_REG_LED_SELECT, RegVal );
+}
+
+bool CApnCamera::read_CoolerEnable()
+{
+ return m_pvtCoolerEnable;
+}
+
+void CApnCamera::write_CoolerEnable( bool CoolerEnable )
+{
+ if ( CoolerEnable )
+ {
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_RAMP_TO_SETPOINT );
+ }
+ else
+ {
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_RAMP_TO_AMBIENT );
+ }
+
+ m_pvtCoolerEnable = CoolerEnable;
+}
+
+Apn_CoolerStatus CApnCamera::read_CoolerStatus()
+{
+ bool CoolerAtTemp;
+ bool CoolerActive;
+ bool CoolerTempRevised;
+
+
+ UpdateGeneralStatus();
+
+ // Update CoolerStatus
+ CoolerActive = false;
+ CoolerAtTemp = false;
+ CoolerTempRevised = false;
+
+ if ( (m_pvtStatusReg & FPGA_BIT_STATUS_TEMP_AT_TEMP) != 0 )
+ CoolerAtTemp = true;
+
+ if ( (m_pvtStatusReg & FPGA_BIT_STATUS_TEMP_ACTIVE) != 0 )
+ CoolerActive = true;
+
+ if ( (m_pvtStatusReg & FPGA_BIT_STATUS_TEMP_REVISION) != 0 )
+ CoolerTempRevised = true;
+
+ // Now derive our cooler state
+ if ( !CoolerActive )
+ {
+ m_pvtCoolerStatus = Apn_CoolerStatus_Off;
+ }
+ else
+ {
+ if ( CoolerTempRevised )
+ {
+ m_pvtCoolerStatus = Apn_CoolerStatus_Revision;
+ }
+ else
+ {
+ if ( CoolerAtTemp )
+ m_pvtCoolerStatus = Apn_CoolerStatus_AtSetPoint;
+ else
+ m_pvtCoolerStatus = Apn_CoolerStatus_RampingToSetPoint;
+
+ }
+ }
+
+ return m_pvtCoolerStatus;
+}
+
+double CApnCamera::read_CoolerSetPoint()
+{
+ unsigned short RegVal;
+ double TempVal;
+
+ Read( FPGA_REG_TEMP_DESIRED, RegVal );
+
+ RegVal &= 0x0FFF;
+
+ TempVal = ( RegVal - APN_TEMP_SETPOINT_ZERO_POINT ) * APN_TEMP_DEGREES_PER_BIT;
+
+ return TempVal;
+}
+
+void CApnCamera::write_CoolerSetPoint( double SetPoint )
+{
+ unsigned short RegVal;
+ double TempVal;
+
+
+ TempVal = SetPoint;
+
+ if ( SetPoint < (APN_TEMP_SETPOINT_MIN - APN_TEMP_KELVIN_SCALE_OFFSET) )
+ TempVal = APN_TEMP_SETPOINT_MIN;
+
+ if ( SetPoint > (APN_TEMP_SETPOINT_MAX - APN_TEMP_KELVIN_SCALE_OFFSET) )
+ TempVal = APN_TEMP_SETPOINT_MAX;
+
+ RegVal = (unsigned short)( (TempVal / APN_TEMP_DEGREES_PER_BIT) + APN_TEMP_SETPOINT_ZERO_POINT );
+
+ Write( FPGA_REG_TEMP_DESIRED, RegVal );
+}
+
+double CApnCamera::read_CoolerBackoffPoint()
+{
+ return ( m_pvtCoolerBackoffPoint );
+}
+
+void CApnCamera::write_CoolerBackoffPoint( double BackoffPoint )
+{
+ unsigned short RegVal;
+ double TempVal;
+
+ TempVal = BackoffPoint;
+
+ // BackoffPoint must be a positive number!
+ if ( BackoffPoint < 0.0 )
+ TempVal = 0.0;
+
+ if ( BackoffPoint < (APN_TEMP_SETPOINT_MIN - APN_TEMP_KELVIN_SCALE_OFFSET) )
+ TempVal = APN_TEMP_SETPOINT_MIN;
+
+ if ( BackoffPoint > (APN_TEMP_SETPOINT_MAX - APN_TEMP_KELVIN_SCALE_OFFSET) )
+ TempVal = APN_TEMP_SETPOINT_MAX;
+
+ m_pvtCoolerBackoffPoint = TempVal;
+
+ RegVal = (unsigned short)( TempVal / APN_TEMP_DEGREES_PER_BIT );
+
+ Write( FPGA_REG_TEMP_BACKOFF, RegVal );
+}
+
+double CApnCamera::read_CoolerDrive()
+{
+ UpdateGeneralStatus();
+
+ return m_pvtCoolerDrive;
+}
+
+double CApnCamera::read_TempCCD()
+{
+ // UpdateGeneralStatus();
+
+ unsigned short TempReg;
+ unsigned short TempAvg;
+ unsigned long TempTotal;
+ int don;
+
+ TempTotal = 0;
+ don = 8;
+ if ( m_CameraInterface == Apn_Interface_NET ) {
+ don = 1;
+ }
+
+ for ( int i=0; i<don; i++ )
+ {
+ Read( FPGA_REG_TEMP_CCD, TempReg );
+ TempTotal += TempReg;
+ }
+
+ TempAvg = (unsigned short)(TempTotal / don);
+
+ m_pvtCurrentCcdTemp = ( (TempAvg - APN_TEMP_SETPOINT_ZERO_POINT)
+ * APN_TEMP_DEGREES_PER_BIT );
+
+ return m_pvtCurrentCcdTemp;
+}
+
+double CApnCamera::read_TempHeatsink()
+{
+ // UpdateGeneralStatus();
+
+ unsigned short TempReg;
+ unsigned short TempAvg;
+ unsigned long TempTotal;
+ int don;
+
+ TempTotal = 0;
+ don = 8;
+ if ( m_CameraInterface == Apn_Interface_NET ) {
+ don = 1;
+ }
+
+ for ( int i=0; i<don; i++ )
+ {
+ Read( FPGA_REG_TEMP_HEATSINK, TempReg );
+ TempTotal += TempReg;
+ }
+
+ TempAvg = (unsigned short)(TempTotal / don);
+
+ m_pvtCurrentHeatsinkTemp = ( (TempAvg - APN_TEMP_HEATSINK_ZERO_POINT)
+ * APN_TEMP_DEGREES_PER_BIT );
+
+ return m_pvtCurrentHeatsinkTemp;
+}
+
+Apn_FanMode CApnCamera::read_FanMode()
+{
+ return m_pvtFanMode;
+}
+
+void CApnCamera::write_FanMode( Apn_FanMode FanMode )
+{
+ unsigned short RegVal;
+ unsigned short OpRegA;
+
+
+ if ( m_pvtFanMode == FanMode )
+ return;
+
+ if ( m_pvtCoolerEnable )
+ {
+ Read( FPGA_REG_OP_A, OpRegA );
+ OpRegA |= FPGA_BIT_TEMP_SUSPEND;
+ Write( FPGA_REG_OP_A, OpRegA );
+
+ do
+ {
+ Read( FPGA_REG_GENERAL_STATUS, RegVal );
+ } while ( (RegVal & FPGA_BIT_STATUS_TEMP_SUSPEND_ACK) == 0 );
+
+ }
+
+ switch ( FanMode )
+ {
+ case Apn_FanMode_Off:
+ RegVal = APN_FAN_SPEED_OFF;
+ break;
+ case Apn_FanMode_Low:
+ RegVal = APN_FAN_SPEED_LOW;
+ break;
+ case Apn_FanMode_Medium:
+ RegVal = APN_FAN_SPEED_MEDIUM;
+ break;
+ case Apn_FanMode_High:
+ RegVal = APN_FAN_SPEED_HIGH;
+ break;
+ }
+
+ Write( FPGA_REG_FAN_SPEED_CONTROL, RegVal );
+
+ Read( FPGA_REG_OP_B, RegVal );
+ RegVal |= FPGA_BIT_DAC_SELECT_ZERO;
+ RegVal &= ~FPGA_BIT_DAC_SELECT_ONE;
+ Write( FPGA_REG_OP_B, RegVal );
+
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_DAC_LOAD );
+
+ m_pvtFanMode = FanMode;
+
+ if ( m_pvtCoolerEnable )
+ {
+ OpRegA &= ~FPGA_BIT_TEMP_SUSPEND;
+ Write( FPGA_REG_OP_A, OpRegA );
+ }
+}
+
+double CApnCamera::read_ShutterStrobePosition()
+{
+ return m_pvtShutterStrobePosition;
+}
+
+void CApnCamera::write_ShutterStrobePosition( double Position )
+{
+ unsigned short RegVal;
+
+ if ( Position < APN_STROBE_POSITION_MIN )
+ Position = APN_STROBE_POSITION_MIN;
+
+ RegVal = (unsigned short)((Position - APN_STROBE_POSITION_MIN) / APN_TIMER_RESOLUTION);
+
+ Write( FPGA_REG_SHUTTER_STROBE_POSITION, RegVal );
+
+ m_pvtShutterStrobePosition = Position;
+}
+
+double CApnCamera::read_ShutterStrobePeriod()
+{
+ return m_pvtShutterStrobePeriod;
+}
+
+void CApnCamera::write_ShutterStrobePeriod( double Period )
+{
+ unsigned short RegVal;
+
+ if ( Period < APN_STROBE_PERIOD_MIN )
+ Period = APN_STROBE_PERIOD_MIN;
+
+ RegVal = (unsigned short)((Period - APN_STROBE_PERIOD_MIN) / APN_PERIOD_TIMER_RESOLUTION);
+
+ Write( FPGA_REG_SHUTTER_STROBE_PERIOD, RegVal );
+
+ m_pvtShutterStrobePeriod = Period;
+}
+
+double CApnCamera::read_SequenceDelay()
+{
+ return m_pvtSequenceDelay;
+}
+
+void CApnCamera::write_SequenceDelay( double Delay )
+{
+ unsigned short RegVal;
+
+ if ( Delay > APN_SEQUENCE_DELAY_LIMIT )
+ Delay = APN_SEQUENCE_DELAY_LIMIT;
+
+ m_pvtSequenceDelay = Delay;
+
+ RegVal = (unsigned short)(Delay / APN_SEQUENCE_DELAY_RESOLUTION);
+
+ Write( FPGA_REG_SEQUENCE_DELAY, RegVal );
+}
+
+bool CApnCamera::read_VariableSequenceDelay()
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_OP_A, RegVal );
+ // variable delay occurs when the bit is 0
+ return ( (RegVal & FPGA_BIT_DELAY_MODE) == 0 );
+}
+
+void CApnCamera::write_VariableSequenceDelay( bool VariableSequenceDelay )
+{
+ unsigned short RegVal;
+
+ Read( FPGA_REG_OP_A, RegVal );
+
+ if ( VariableSequenceDelay )
+ RegVal &= ~FPGA_BIT_DELAY_MODE; // variable when zero
+ else
+ RegVal |= FPGA_BIT_DELAY_MODE; // constant when one
+
+ Write( FPGA_REG_OP_A, RegVal );
+}
+
+unsigned short CApnCamera::read_ImageCount()
+{
+ return m_pvtImageCount;
+}
+
+void CApnCamera::write_ImageCount( unsigned short Count )
+{
+ if ( Count == 0 )
+ Count = 1;
+
+ Write( FPGA_REG_IMAGE_COUNT, Count );
+
+ m_pvtImageCount = Count;
+}
+
+void CApnCamera::write_RoiBinningH( unsigned short BinningH )
+{
+ // Check to see if we actually need to update the binning
+ if ( BinningH != m_RoiBinningH )
+ {
+ // Reset the camera
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_RESET );
+
+ LoadRoiPattern( BinningH );
+ m_RoiBinningH = BinningH;
+
+ // Reset the camera
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_RESET );
+
+ // Start flushing
+ Write( FPGA_REG_COMMAND_A, FPGA_BIT_CMD_FLUSH );
+ }
+}
+
+void CApnCamera::write_RoiBinningV( unsigned short BinningV )
+{
+ // Check to see if we actually need to update the binning
+ if ( BinningV != m_RoiBinningV )
+ {
+ m_RoiBinningV = BinningV;
+ }
+}
+
+void CApnCamera::write_RoiPixelsV( unsigned short PixelsV )
+{
+ m_RoiPixelsV = PixelsV;
+}
+
+void CApnCamera::write_RoiStartY( unsigned short StartY )
+{
+ m_RoiStartY = StartY;
+}
+
+unsigned short CApnCamera::read_OverscanColumns()
+{
+ return m_ApnSensorInfo->m_OverscanColumns;
+}
+
+unsigned short CApnCamera::read_MaxBinningV()
+{
+ if ( m_ApnSensorInfo->m_ImagingRows < APN_VBINNING_MAX )
+ return m_ApnSensorInfo->m_ImagingRows;
+ else
+ return APN_VBINNING_MAX;
+}
+
+unsigned short CApnCamera::read_SequenceCounter()
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_SEQUENCE_COUNTER, RegVal );
+ return RegVal;
+}
+
+unsigned short CApnCamera::read_TDICounter()
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_TDI_COUNTER, RegVal );
+ return RegVal;
+}
+
+unsigned short CApnCamera::read_TDIRows()
+{
+ return m_pvtTDIRows;
+}
+
+void CApnCamera::write_TDIRows( unsigned short TdiRows )
+{
+ if ( TdiRows == 0 ) // Make sure the TDI row count is at least 1
+ TdiRows = 1;
+
+ Write( FPGA_REG_TDI_COUNT, TdiRows );
+ m_pvtTDIRows = TdiRows;
+}
+
+double CApnCamera::read_TDIRate()
+{
+ return m_pvtTDIRate;
+}
+
+void CApnCamera::write_TDIRate( double TdiRate )
+{
+ unsigned short RegVal;
+
+ if ( TdiRate < APN_TDI_RATE_MIN )
+ TdiRate = APN_TDI_RATE_MIN;
+
+ if ( TdiRate > APN_TDI_RATE_MAX )
+ TdiRate = APN_TDI_RATE_MAX;
+
+ RegVal = (unsigned short)( TdiRate / APN_TDI_RATE_RESOLUTION );
+
+ Write( FPGA_REG_TDI_RATE, RegVal );
+
+ m_pvtTDIRate = TdiRate;
+}
+
+unsigned short CApnCamera::read_IoPortAssignment()
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_IO_PORT_ASSIGNMENT, RegVal );
+ RegVal &= FPGA_MASK_IO_PORT_ASSIGNMENT;
+ return RegVal;
+}
+
+void CApnCamera::write_IoPortAssignment( unsigned short IoPortAssignment )
+{
+ IoPortAssignment &= FPGA_MASK_IO_PORT_ASSIGNMENT;
+ Write( FPGA_REG_IO_PORT_ASSIGNMENT, IoPortAssignment );
+}
+
+unsigned short CApnCamera::read_IoPortDirection()
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_IO_PORT_DIRECTION, RegVal );
+ RegVal &= FPGA_MASK_IO_PORT_DIRECTION;
+ return RegVal;
+}
+
+void CApnCamera::write_IoPortDirection( unsigned short IoPortDirection )
+{
+ IoPortDirection &= FPGA_MASK_IO_PORT_DIRECTION;
+ Write( FPGA_REG_IO_PORT_DIRECTION, IoPortDirection );
+}
+
+unsigned short CApnCamera::read_IoPortData()
+{
+ unsigned short RegVal;
+ Read( FPGA_REG_IO_PORT_READ, RegVal );
+ RegVal &= FPGA_MASK_IO_PORT_DATA;
+ return RegVal;
+}
+
+void CApnCamera::write_IoPortData( unsigned short IoPortData )
+{
+ IoPortData &= FPGA_MASK_IO_PORT_DATA;
+ Write( FPGA_REG_IO_PORT_WRITE, IoPortData );
+}
+
+unsigned short CApnCamera::read_TwelveBitGain()
+{
+ return m_pvtTwelveBitGain;
+}
+
+void CApnCamera::write_TwelveBitGain( unsigned short TwelveBitGain )
+{
+ unsigned short NewVal;
+ unsigned short StartVal;
+ unsigned short FirstBit;
+
+ NewVal = 0x0;
+ StartVal = TwelveBitGain & 0x3FF;
+
+ for ( int i=0; i<10; i++ )
+ {
+ FirstBit = ( StartVal & 0x0001 );
+ NewVal |= ( FirstBit << (10-i) );
+ StartVal = StartVal >> 1;
+ }
+
+ NewVal |= 0x4000;
+
+ Write( FPGA_REG_AD_CONFIG_DATA, NewVal );
+ Write( FPGA_REG_COMMAND_B, 0x8000 );
+
+ m_pvtTwelveBitGain = TwelveBitGain & 0x3FF;
+}
+
+double CApnCamera::read_MaxExposureTime()
+{
+ return APN_EXPOSURE_TIME_MAX;
+}
+
+double CApnCamera::read_TestLedBrightness()
+{
+ return m_pvtTestLedBrightness;
+}
+
+void CApnCamera::write_TestLedBrightness( double TestLedBrightness )
+{
+ unsigned short RegVal;
+ unsigned short OpRegA;
+
+
+ if ( TestLedBrightness == m_pvtTestLedBrightness )
+ return;
+
+ if ( m_pvtCoolerEnable )
+ {
+ Read( FPGA_REG_OP_A, OpRegA );
+ OpRegA |= FPGA_BIT_TEMP_SUSPEND;
+ Write( FPGA_REG_OP_A, OpRegA );
+
+ do
+ {
+ Read( FPGA_REG_GENERAL_STATUS, RegVal );
+ } while ( (RegVal & FPGA_BIT_STATUS_TEMP_SUSPEND_ACK) == 0 );
+
+ }
+
+ RegVal = (unsigned short)( (double)FPGA_MASK_LED_ILLUMINATION * (TestLedBrightness/100.0) );
+
+ Write( FPGA_REG_LED_DRIVE, RegVal );
+
+ Read( FPGA_REG_OP_B, RegVal );
+ RegVal &= ~FPGA_BIT_DAC_SELECT_ZERO;
+ RegVal |= FPGA_BIT_DAC_SELECT_ONE;
+ Write( FPGA_REG_OP_B, RegVal );
+
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_DAC_LOAD );
+
+ m_pvtTestLedBrightness = TestLedBrightness;
+
+ if ( m_pvtCoolerEnable )
+ {
+ OpRegA &= ~FPGA_BIT_TEMP_SUSPEND;
+ Write( FPGA_REG_OP_A, OpRegA );
+ }
+}
+
+
+
+
+
+
+
+
+long CApnCamera::LoadVerticalPattern()
+{
+ unsigned short RegData;
+
+ // Prime the RAM (Enable)
+ Read( FPGA_REG_OP_B, RegData );
+ RegData |= FPGA_BIT_VRAM_ENABLE;
+ Write( FPGA_REG_OP_B, RegData );
+
+ WriteMultiSRMD( FPGA_REG_VRAM_INPUT,
+ m_ApnSensorInfo->m_VerticalPattern.PatternData,
+ m_ApnSensorInfo->m_VerticalPattern.NumElements );
+
+ // RAM is now loaded (Disable)
+ Read( FPGA_REG_OP_B, RegData );
+ RegData &= ~FPGA_BIT_VRAM_ENABLE;
+ Write( FPGA_REG_OP_B, RegData );
+
+ return 0;
+}
+
+
+long CApnCamera::LoadClampPattern()
+{
+ unsigned short RegData;
+
+ // Prime the RAM (Enable)
+ Read( FPGA_REG_OP_B, RegData );
+ RegData |= FPGA_BIT_HCLAMP_ENABLE;
+ Write( FPGA_REG_OP_B, RegData );
+
+ if ( m_DataBits == Apn_Resolution_SixteenBit )
+ {
+ WriteHorizontalPattern( &m_ApnSensorInfo->m_ClampPatternSixteen,
+ FPGA_REG_HCLAMP_INPUT,
+ 1 );
+ }
+ else if ( m_DataBits == Apn_Resolution_TwelveBit )
+ {
+ WriteHorizontalPattern( &m_ApnSensorInfo->m_ClampPatternTwelve,
+ FPGA_REG_HCLAMP_INPUT,
+ 1 );
+ }
+
+ // RAM is now loaded (Disable)
+ Read( FPGA_REG_OP_B, RegData );
+ RegData &= ~FPGA_BIT_HCLAMP_ENABLE;
+ Write( FPGA_REG_OP_B, RegData );
+
+ return 0;
+}
+
+
+long CApnCamera::LoadSkipPattern()
+{
+ unsigned short RegData;
+
+ // Prime the RAM (Enable)
+ Read( FPGA_REG_OP_B, RegData );
+ RegData |= FPGA_BIT_HSKIP_ENABLE;
+ Write( FPGA_REG_OP_B, RegData );
+
+ if ( m_DataBits == Apn_Resolution_SixteenBit )
+ {
+ WriteHorizontalPattern( &m_ApnSensorInfo->m_SkipPatternSixteen,
+ FPGA_REG_HSKIP_INPUT,
+ 1 );
+ }
+ else if ( m_DataBits == Apn_Resolution_TwelveBit )
+ {
+ WriteHorizontalPattern( &m_ApnSensorInfo->m_SkipPatternTwelve,
+ FPGA_REG_HSKIP_INPUT,
+ 1 );
+ }
+
+ // RAM is now loaded (Disable)
+ Read( FPGA_REG_OP_B, RegData );
+ RegData &= ~FPGA_BIT_HSKIP_ENABLE;
+ Write( FPGA_REG_OP_B, RegData );
+
+ return 0;
+}
+
+
+long CApnCamera::LoadRoiPattern( unsigned short binning )
+{
+ unsigned short RegData;
+
+ // Prime the RAM (Enable)
+ Read( FPGA_REG_OP_B, RegData );
+ RegData |= FPGA_BIT_HRAM_ENABLE;
+ Write( FPGA_REG_OP_B, RegData );
+
+ if ( m_DataBits == Apn_Resolution_SixteenBit )
+ {
+ WriteHorizontalPattern( &m_ApnSensorInfo->m_RoiPatternSixteen,
+ FPGA_REG_HRAM_INPUT,
+ binning );
+ }
+ else if ( m_DataBits == Apn_Resolution_TwelveBit )
+ {
+ WriteHorizontalPattern( &m_ApnSensorInfo->m_RoiPatternTwelve,
+ FPGA_REG_HRAM_INPUT,
+ binning );
+ }
+
+ // RAM is now loaded (Disable)
+ Read( FPGA_REG_OP_B, RegData );
+ RegData &= ~FPGA_BIT_HRAM_ENABLE;
+ Write( FPGA_REG_OP_B, RegData );
+
+ return 0;
+}
+
+
+long CApnCamera::WriteHorizontalPattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short RamReg,
+ unsigned short Binning )
+{
+ unsigned short i;
+ unsigned short DataCount;
+ unsigned short *DataArray;
+ unsigned short Index;
+ unsigned short BinNumber;
+
+
+ Index = 0;
+ BinNumber = Binning - 1; // arrays are zero-based
+
+ DataCount = Pattern->RefNumElements +
+ Pattern->BinNumElements[BinNumber] +
+ Pattern->SigNumElements;
+
+ DataArray = (unsigned short *)malloc(DataCount * sizeof(unsigned short));
+
+ for ( i=0; i<Pattern->RefNumElements; i++ )
+ {
+ DataArray[Index] = Pattern->RefPatternData[i];
+ Index++;
+ }
+
+ for ( i=0; i<Pattern->BinNumElements[BinNumber]; i++ )
+ {
+ DataArray[Index] = Pattern->BinPatternData[BinNumber][i];
+ Index++;
+ }
+
+ for ( i=0; i<Pattern->SigNumElements; i++ )
+ {
+ DataArray[Index] = Pattern->SigPatternData[i];
+ Index++;
+ }
+
+ WriteMultiSRMD( RamReg, DataArray, DataCount );
+
+ // cleanup
+ free( DataArray );
+
+ return 0;
+}
+
+
+long CApnCamera::InitDefaults()
+{
+ unsigned short RegVal;
+ unsigned short CameraID;
+ unsigned short ShutterDelay;
+
+ unsigned short PreRoiRows, PostRoiRows;
+ unsigned short PreRoiVBinning, PostRoiVBinning;
+ unsigned short UnbinnedRoiY; // Vertical ROI pixels
+
+
+ // Read the Camera ID register
+ Read( FPGA_REG_CAMERA_ID, CameraID );
+ CameraID &= FPGA_MASK_CAMERA_ID;
+
+ // Look up the ID and dynamically create the m_ApnSensorInfo object
+ switch ( CameraID )
+ {
+ case APN_ALTA_KAF0401E_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_KAF0401E;
+ break;
+ case APN_ALTA_KAF1602E_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_KAF1602E;
+ break;
+ case APN_ALTA_KAF0261E_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_KAF0261E;
+ break;
+ case APN_ALTA_KAF1301E_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_KAF1301E;
+ break;
+ case APN_ALTA_KAF1401E_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_KAF1401E;
+ break;
+ case APN_ALTA_KAF1001E_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_KAF1001E;
+ break;
+ case APN_ALTA_KAF3200E_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_KAF3200E;
+ break;
+ case APN_ALTA_KAF4202_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_KAF4202;
+ break;
+ case APN_ALTA_KAF6303E_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_KAF6303E;
+ break;
+ case APN_ALTA_KAF16801E_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_KAF16801E;
+ break;
+ case APN_ALTA_TH7899_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_TH7899;
+ break;
+ case APN_ALTA_CCD4710LS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD4710LS;
+ break;
+ case APN_ALTA_CCD4710HS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD4710HS;
+ break;
+ case APN_ALTA_CCD4240LS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD4240LS;
+ break;
+ case APN_ALTA_CCD4240HS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD4240HS;
+ break;
+ case APN_ALTA_CCD5710LS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD5710LS;
+ break;
+ case APN_ALTA_CCD5710HS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD5710HS;
+ break;
+ case APN_ALTA_CCD3011LS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD3011LS;
+ break;
+ case APN_ALTA_CCD3011HS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD3011HS;
+ break;
+ case APN_ALTA_CCD5520LS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD5520LS;
+ break;
+ case APN_ALTA_CCD5520HS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD5520HS;
+ break;
+ case APN_ALTA_CCD4720LS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD4720LS;
+ break;
+ case APN_ALTA_CCD4720HS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD4720HS;
+ break;
+ case APN_ALTA_CCD7700LS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD7700LS;
+ break;
+ case APN_ALTA_CCD7700HS_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD7700HS;
+ break;
+ case APN_ALTA_CCD4710LS2_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD4710LS2;
+ break;
+ case APN_ALTA_CCD4710LS3_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD4710LS3;
+ break;
+ case APN_ALTA_CCD4710LS4_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD4710LS4;
+ break;
+ case APN_ALTA_CCD4710LS5_CAM_ID:
+ m_ApnSensorInfo = new CApnCamData_CCD4710LS5;
+ break;
+ default:
+ return 1;
+ break;
+ }
+
+ // we created the object, now set everything
+ m_ApnSensorInfo->Initialize();
+
+ // Initialize public variables
+ m_DigitizeOverscan = false;
+ m_DataBits = Apn_Resolution_SixteenBit;
+
+ // Initialize private variables
+ m_pvtCameraMode = Apn_CameraMode_Normal;
+ m_pvtNetworkTransferMode = Apn_NetworkMode_Tcp;
+
+ // Initialize variables used for imaging
+ m_RoiStartX = 0;
+ m_RoiStartY = 0;
+ m_RoiPixelsH = m_ApnSensorInfo->m_ImagingColumns;
+ m_RoiPixelsV = m_ApnSensorInfo->m_ImagingRows;
+
+ m_RoiBinningH = 1;
+ m_RoiBinningV = 1;
+ printf ("Camera ID is %u\n",CameraID);
+ printf("sensor = %s\n", m_ApnSensorInfo->m_Sensor);
+ printf("model = %s\n",m_ApnSensorInfo->m_CameraModel);
+ printf("interline = %u\n",m_ApnSensorInfo->m_InterlineCCD);
+ printf("serialA = %u\n",m_ApnSensorInfo->m_SupportsSerialA);
+ printf("serialB = %u\n",m_ApnSensorInfo->m_SupportsSerialB);
+ printf("ccdtype = %u\n",m_ApnSensorInfo->m_SensorTypeCCD);
+ printf("Tcolumns = %u\n",m_ApnSensorInfo->m_TotalColumns);
+ printf("ImgColumns = %u\n",m_ApnSensorInfo->m_ImagingColumns);
+ printf("ClampColumns = %u\n",m_ApnSensorInfo->m_ClampColumns);
+ printf("PreRoiSColumns = %u\n",m_ApnSensorInfo->m_PreRoiSkipColumns);
+ printf("PostRoiSColumns = %u\n",m_ApnSensorInfo->m_PostRoiSkipColumns);
+ printf("OverscanColumns = %u\n",m_ApnSensorInfo->m_OverscanColumns);
+ printf("TRows = %u\n",m_ApnSensorInfo->m_TotalRows);
+ printf("ImgRows = %u\n",m_ApnSensorInfo->m_ImagingRows);
+ printf("UnderscanRows = %u\n",m_ApnSensorInfo->m_UnderscanRows);
+ printf("OverscanRows = %u\n",m_ApnSensorInfo->m_OverscanRows);
+ printf("VFlushBinning = %u\n",m_ApnSensorInfo->m_VFlushBinning);
+ printf("HFlushDisable = %u\n",m_ApnSensorInfo->m_HFlushDisable);
+ printf("ShutterCloseDelay = %u\n",m_ApnSensorInfo->m_ShutterCloseDelay);
+ printf("PixelSizeX = %lf\n",m_ApnSensorInfo->m_PixelSizeX);
+ printf("PixelSizeY = %lf\n",m_ApnSensorInfo->m_PixelSizeY);
+ printf("Color = %u\n",m_ApnSensorInfo->m_Color);
+// printf("ReportedGainTwelveBit = %lf\n",m_ApnSensorInfo->m_ReportedGainTwelveBit);
+ printf("ReportedGainSixteenBit = %lf\n",m_ApnSensorInfo->m_ReportedGainSixteenBit);
+ printf("MinSuggestedExpTime = %lf\n",m_ApnSensorInfo->m_MinSuggestedExpTime);
+ printf("CoolingSupported = %u\n",m_ApnSensorInfo->m_CoolingSupported);
+ printf("RegulatedCoolingSupported = %u\n",m_ApnSensorInfo->m_RegulatedCoolingSupported);
+ printf("TempSetPoint = %lf\n",m_ApnSensorInfo->m_TempSetPoint);
+// printf("TempRegRate = %u\n",m_ApnSensorInfo->m_TempRegRate);
+ printf("TempRampRateOne = %u\n",m_ApnSensorInfo->m_TempRampRateOne);
+ printf("TempRampRateTwo = %u\n",m_ApnSensorInfo->m_TempRampRateTwo);
+ printf("TempBackoffPoint = %lf\n",m_ApnSensorInfo->m_TempBackoffPoint);
+ printf("DefaultGainTwelveBit = %u\n",m_ApnSensorInfo->m_DefaultGainTwelveBit);
+ printf("DefaultOffsetTwelveBit = %u\n",m_ApnSensorInfo->m_DefaultOffsetTwelveBit);
+ printf("DefaultRVoltage = %u\n",m_ApnSensorInfo->m_DefaultRVoltage);
+
+
+
+ printf ("RoiPixelsH is %u\n",m_RoiPixelsH);
+ printf ("RoiPixelsV is %u\n",m_RoiPixelsV);
+
+
+ // Issue a clear command, so the registers are zeroed out
+ // This will put the camera in a known state for us.
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_CLEAR_ALL );
+
+ // Reset the camera
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_RESET );
+
+ // Load Inversion Masks
+ Write( FPGA_REG_VRAM_INV_MASK, m_ApnSensorInfo->m_VerticalPattern.Mask );
+ Write( FPGA_REG_HRAM_INV_MASK, m_ApnSensorInfo->m_RoiPatternSixteen.Mask );
+
+ // Load Pattern Files
+ LoadVerticalPattern();
+ LoadClampPattern();
+ LoadSkipPattern();
+ LoadRoiPattern( m_RoiBinningH );
+
+ // Program default camera settings
+ Write( FPGA_REG_CLAMP_COUNT, m_ApnSensorInfo->m_ClampColumns );
+ Write( FPGA_REG_PREROI_SKIP_COUNT, m_ApnSensorInfo->m_PreRoiSkipColumns );
+ Write( FPGA_REG_ROI_COUNT, m_ApnSensorInfo->m_ImagingColumns );
+ Write( FPGA_REG_POSTROI_SKIP_COUNT, m_ApnSensorInfo->m_PostRoiSkipColumns +
+ m_ApnSensorInfo->m_OverscanColumns );
+
+ // Since the default state of m_DigitizeOverscan is false, set the count to zero.
+ Write( FPGA_REG_OVERSCAN_COUNT, 0x0 );
+
+ // Now calculate the vertical settings
+ UnbinnedRoiY = m_RoiPixelsV * m_RoiBinningV;
+
+ PreRoiRows = m_ApnSensorInfo->m_UnderscanRows +
+ m_RoiStartY;
+
+ PostRoiRows = m_ApnSensorInfo->m_TotalRows -
+ PreRoiRows -
+ UnbinnedRoiY;
+
+ PreRoiVBinning = 1;
+ PostRoiVBinning = 1;
+
+ // For interline CCDs, set "Fast Dump" mode if the particular array is NOT digitized
+ if ( m_ApnSensorInfo->m_InterlineCCD )
+ {
+ // use the fast dump feature to get rid of the data quickly.
+ // one row, binning to the original row count
+ // note that we only are not digitized in arrays 1 and 3
+ PreRoiVBinning = PreRoiRows;
+ PostRoiVBinning = PostRoiRows;
+
+ PreRoiVBinning |= FPGA_BIT_ARRAY_FASTDUMP;
+ PostRoiVBinning |= FPGA_BIT_ARRAY_FASTDUMP;
+
+ PreRoiRows = 1;
+ PostRoiRows = 1;
+ }
+
+ // Program the vertical settings
+ Write( FPGA_REG_A1_ROW_COUNT, PreRoiRows );
+ Write( FPGA_REG_A1_VBINNING, PreRoiVBinning );
+
+ Write( FPGA_REG_A2_ROW_COUNT, m_RoiPixelsV );
+ Write( FPGA_REG_A2_VBINNING, (m_RoiBinningV | FPGA_BIT_ARRAY_DIGITIZE) );
+
+ Write( FPGA_REG_A3_ROW_COUNT, PostRoiRows );
+ Write( FPGA_REG_A3_VBINNING, PostRoiVBinning );
+
+ Write( FPGA_REG_VFLUSH_BINNING, m_ApnSensorInfo->m_VFlushBinning );
+
+ double CloseDelay = (double)m_ApnSensorInfo->m_ShutterCloseDelay / 1000;
+ ShutterDelay = (unsigned short)
+ ( (CloseDelay - APN_SHUTTER_CLOSE_DIFF) / APN_TIMER_RESOLUTION );
+
+ Write( FPGA_REG_SHUTTER_CLOSE_DELAY, ShutterDelay );
+
+ Write( FPGA_REG_IMAGE_COUNT, 1 );
+ Write( FPGA_REG_SEQUENCE_DELAY, 0 );
+
+ if ( m_ApnSensorInfo->m_HFlushDisable )
+ {
+ Read( FPGA_REG_OP_A, RegVal );
+
+ RegVal |= FPGA_BIT_DISABLE_H_CLK;
+
+ Write( FPGA_REG_OP_A, RegVal );
+ }
+
+ // Reset the camera again
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_RESET );
+
+ // Start flushing
+ Write( FPGA_REG_COMMAND_A, FPGA_BIT_CMD_FLUSH );
+
+ // If we are a USB2 camera, set all the 12bit variables for the 12bit
+ // A/D processor
+ if ( m_CameraInterface == Apn_Interface_USB )
+ {
+ InitTwelveBitAD();
+ write_TwelveBitGain( m_ApnSensorInfo->m_DefaultGainTwelveBit );
+ WriteTwelveBitOffset();
+ }
+
+ // Set the Fan State. Setting the private var first to make sure the write_FanMode
+ // call thinks we're doing a state transition.
+ // On write_FanMode return, our state will be Apn_FanMode_Medium
+ m_pvtFanMode = Apn_FanMode_Off; // we're going to set this
+ write_FanMode( Apn_FanMode_Medium );
+
+ // Initialize the LED states and the LED mode. There is nothing to output
+ // to the device since we issued our CLEAR early in the init() process, and
+ // we are now in a known state.
+ m_pvtLedStateA = Apn_LedState_Expose;
+ m_pvtLedStateB = Apn_LedState_Expose;
+ m_pvtLedMode = Apn_LedMode_EnableAll;
+
+ // Default value for test LED is 0%
+ m_pvtTestLedBrightness = 0.0;
+
+ // Program our initial cooler values. The only cooler value that we reset
+ // at init time is the backoff point. Everything else is left untouched, and
+ // state information is determined from the camera controller.
+ m_pvtCoolerBackoffPoint = m_ApnSensorInfo->m_TempBackoffPoint;
+ write_CoolerBackoffPoint( m_pvtCoolerBackoffPoint );
+ Write( FPGA_REG_TEMP_RAMP_DOWN_A, m_ApnSensorInfo->m_TempRampRateOne );
+ Write( FPGA_REG_TEMP_RAMP_DOWN_B, m_ApnSensorInfo->m_TempRampRateTwo );
+ // the collor code not only determines the m_pvtCoolerEnable state, but
+ // also implicitly calls UpdateGeneralStatus() as part of read_CoolerStatus()
+ if ( read_CoolerStatus() == Apn_CoolerStatus_Off )
+ m_pvtCoolerEnable = false;
+ else
+ m_pvtCoolerEnable = true;
+
+ m_pvtImageInProgress = false;
+ m_pvtImageReady = false;
+
+ return 0;
+}
+
+long CApnCamera::InitTwelveBitAD()
+{
+ Write( FPGA_REG_AD_CONFIG_DATA, 0x0028 );
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_AD_CONFIG );
+
+ return 0;
+}
+
+long CApnCamera::WriteTwelveBitOffset()
+{
+ unsigned short NewVal;
+ unsigned short StartVal;
+ unsigned short FirstBit;
+
+
+ NewVal = 0x0;
+ StartVal = m_ApnSensorInfo->m_DefaultOffsetTwelveBit & 0xFF;
+
+ for ( int i=0; i<8; i++ )
+ {
+ FirstBit = ( StartVal & 0x0001 );
+ NewVal |= ( FirstBit << (10-i) );
+ StartVal = StartVal >> 1;
+ }
+
+ NewVal |= 0x2000;
+
+ Write( FPGA_REG_AD_CONFIG_DATA, NewVal );
+ Write( FPGA_REG_COMMAND_B, FPGA_BIT_CMD_AD_CONFIG );
+
+ return 0;
+}
+
+void CApnCamera::UpdateGeneralStatus()
+{
+ unsigned short StatusReg;
+ unsigned short HeatsinkTempReg;
+ unsigned short CcdTempReg;
+ unsigned short CoolerDriveReg;
+ unsigned short VoltageReg;
+ unsigned short TdiCounterReg;
+ unsigned short SequenceCounterReg;
+
+
+
+ // Read the general status register of the device
+ QueryStatusRegs( StatusReg,
+ HeatsinkTempReg,
+ CcdTempReg,
+ CoolerDriveReg,
+ VoltageReg,
+ TdiCounterReg,
+ SequenceCounterReg );
+
+ m_pvtStatusReg = StatusReg;
+
+ HeatsinkTempReg &= FPGA_MASK_TEMP_PARAMS;
+ CcdTempReg &= FPGA_MASK_TEMP_PARAMS;
+ CoolerDriveReg &= FPGA_MASK_TEMP_PARAMS;
+ VoltageReg &= FPGA_MASK_INPUT_VOLTAGE;
+
+ if ( CoolerDriveReg > 3200 )
+ m_pvtCoolerDrive = 100.0;
+ else
+ m_pvtCoolerDrive = ( (double)(CoolerDriveReg - 600) / 2600.0 ) * 100.0;
+
+ m_pvtCurrentCcdTemp = ( (CcdTempReg - APN_TEMP_SETPOINT_ZERO_POINT)
+ * APN_TEMP_DEGREES_PER_BIT );
+
+ m_pvtCurrentHeatsinkTemp = ( (HeatsinkTempReg - APN_TEMP_HEATSINK_ZERO_POINT)
+ * APN_TEMP_DEGREES_PER_BIT );
+
+ m_pvtInputVoltage = VoltageReg * APN_VOLTAGE_RESOLUTION;
+
+ // Update ShutterState
+ m_pvtShutterState = ( (m_pvtStatusReg & FPGA_BIT_STATUS_SHUTTER_OPEN) != 0 );
+}
+
+
+bool CApnCamera::ImageReady()
+{
+ return m_pvtImageReady;
+}
+
+
+void CApnCamera::SignalImagingDone()
+{
+ m_pvtImageInProgress = false;
+}
+
+
+
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamera.h b/kstars/kstars/indi/apogee/ApnCamera.h
new file mode 100644
index 00000000..b0e6af03
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamera.h
@@ -0,0 +1,332 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+// ApnCamera.h: interface for the CApnCamera class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_APNCAMERA_H__CF513996_359F_4103_BBA6_2C730AE2C301__INCLUDED_)
+#define AFX_APNCAMERA_H__CF513996_359F_4103_BBA6_2C730AE2C301__INCLUDED_
+
+#include "Apogee.h"
+#include "Apn.h"
+#include "FpgaRegs.h"
+
+#include "ApnCamData.h"
+#include "ApnCamData_CCD3011HS.h"
+#include "ApnCamData_CCD3011LS.h"
+#include "ApnCamData_CCD4240HS.h"
+#include "ApnCamData_CCD4240LS.h"
+#include "ApnCamData_CCD4710HS.h"
+#include "ApnCamData_CCD4710LS.h"
+#include "ApnCamData_CCD4720HS.h"
+#include "ApnCamData_CCD4720LS.h"
+#include "ApnCamData_CCD5520HS.h"
+#include "ApnCamData_CCD5520LS.h"
+#include "ApnCamData_CCD5710HS.h"
+#include "ApnCamData_CCD5710LS.h"
+#include "ApnCamData_CCD7700HS.h"
+#include "ApnCamData_CCD7700LS.h"
+#include "ApnCamData_KAF0261E.h"
+#include "ApnCamData_KAF0401E.h"
+#include "ApnCamData_KAF1001E.h"
+#include "ApnCamData_KAF1301E.h"
+#include "ApnCamData_KAF1401E.h"
+#include "ApnCamData_KAF1602E.h"
+#include "ApnCamData_KAF16801E.h"
+#include "ApnCamData_KAF3200E.h"
+#include "ApnCamData_KAF4202.h"
+#include "ApnCamData_KAF6303E.h"
+#include "ApnCamData_TH7899.h"
+
+#include "ApnCamData_CCD4710LS2.h"
+#include "ApnCamData_CCD4710LS3.h"
+#include "ApnCamData_CCD4710LS4.h"
+#include "ApnCamData_CCD4710LS5.h"
+
+
+class CApnCamera
+{
+public:
+ CApnCamera();
+ ~CApnCamera();
+
+ bool InitDriver( unsigned long CamIdA,
+ unsigned short CamIdB,
+ unsigned long Option );
+
+ bool CloseDriver();
+ long PreStartExpose( unsigned short BitsPerPixel );
+ long PostStopExposure( bool DigitizeData );
+
+ bool GetImageData( unsigned short *pImageData,
+ unsigned short &Width,
+ unsigned short &Height,
+ unsigned long &Count );
+
+ bool GetLineData( unsigned short *pLineBuffer,
+ unsigned short &Size );
+
+ long Read( unsigned short reg, unsigned short& val );
+ long Write( unsigned short reg, unsigned short val );
+
+ long WriteMultiSRMD( unsigned short reg,
+ unsigned short val[],
+ unsigned short count );
+
+ long WriteMultiMRMD( unsigned short reg[],
+ unsigned short val[],
+ unsigned short count );
+
+ long QueryStatusRegs( unsigned short& StatusReg,
+ unsigned short& HeatsinkTempReg,
+ unsigned short& CcdTempReg,
+ unsigned short& CoolerDriveReg,
+ unsigned short& VoltageReg,
+ unsigned short& TdiCounter,
+ unsigned short& SequenceCounter );
+
+ void SetNetworkTransferMode( Apn_NetworkMode TransferMode );
+
+ long InitDefaults();
+
+ bool Expose( double Duration, bool Light );
+ bool BufferImage(char *bufferName );
+ bool BufferDriftScan(char *bufferName, int delay, int rowCount, int nblock , int npipe);
+
+ bool StopExposure( bool DigitizeData );
+
+ bool ResetSystem();
+ bool PauseTimer( bool PauseState );
+
+
+ unsigned short GetExposurePixelsH();
+ unsigned short GetExposurePixelsV();
+
+ bool read_Present();
+ unsigned short read_FirmwareVersion();
+
+ bool read_ShutterState();
+ bool read_DisableShutter();
+ void write_DisableShutter( bool DisableShutter );
+ bool read_ForceShutterOpen();
+ void write_ForceShutterOpen( bool ForceShutterOpen );
+ bool read_ShutterAmpControl();
+ void write_ShutterAmpControl( bool ShutterAmpControl );
+
+ bool read_ExternalIoReadout();
+ void write_ExternalIoReadout( bool ExternalIoReadout );
+ bool read_FastSequence();
+ void write_FastSequence( bool FastSequence );
+
+ Apn_CameraMode read_CameraMode();
+ void write_CameraMode( Apn_CameraMode CameraMode );
+
+ void write_DataBits( Apn_Resolution BitResolution );
+
+ Apn_Status read_ImagingStatus();
+
+ Apn_LedMode read_LedMode();
+ void write_LedMode( Apn_LedMode LedMode );
+ Apn_LedState read_LedState( unsigned short LedId );
+ void write_LedState( unsigned short LedId, Apn_LedState LedState );
+
+ bool read_CoolerEnable();
+ void write_CoolerEnable( bool CoolerEnable );
+ Apn_CoolerStatus read_CoolerStatus();
+ double read_CoolerSetPoint();
+ void write_CoolerSetPoint( double SetPoint );
+ double read_CoolerBackoffPoint();
+ void write_CoolerBackoffPoint( double BackoffPoint );
+ double read_CoolerDrive();
+ double read_TempCCD();
+ double read_TempHeatsink();
+ Apn_FanMode read_FanMode();
+ void write_FanMode( Apn_FanMode FanMode );
+
+ void write_RoiBinningH( unsigned short BinningH );
+ void write_RoiBinningV( unsigned short BinningV );
+
+ void write_RoiPixelsV( unsigned short PixelsV );
+
+ void write_RoiStartY( unsigned short StartY );
+
+ unsigned short read_MaxBinningV();
+ unsigned short read_OverscanColumns();
+
+ double read_ShutterStrobePosition();
+ void write_ShutterStrobePosition( double Position );
+ double read_ShutterStrobePeriod();
+ void write_ShutterStrobePeriod( double Period );
+
+ double read_SequenceDelay();
+ void write_SequenceDelay( double Delay );
+ bool read_VariableSequenceDelay();
+ void write_VariableSequenceDelay( bool VariableSequenceDelay );
+ unsigned short read_ImageCount();
+ void write_ImageCount( unsigned short Count );
+
+ unsigned short read_SequenceCounter();
+ unsigned short read_TDICounter();
+ unsigned short read_TDIRows();
+ void write_TDIRows( unsigned short TdiRows );
+ double read_TDIRate();
+ void write_TDIRate( double TdiRate );
+ unsigned short read_IoPortAssignment();
+ void write_IoPortAssignment( unsigned short IoPortAssignment );
+ unsigned short read_IoPortDirection();
+ void write_IoPortDirection( unsigned short IoPortDirection );
+ unsigned short read_IoPortData();
+ void write_IoPortData( unsigned short IoPortData );
+
+ unsigned short read_TwelveBitGain();
+ void write_TwelveBitGain( unsigned short TwelveBitGain );
+
+ double read_InputVoltage();
+ long read_AvailableMemory();
+
+ double read_MaxExposureTime();
+
+ Apn_NetworkMode read_NetworkTransferMode();
+ void write_NetworkTransferMode( Apn_NetworkMode TransferMode );
+
+ double read_TestLedBrightness();
+ void write_TestLedBrightness( double TestLedBrightness );
+
+
+ // Public helper function
+ bool ImageReady();
+ void SignalImagingDone();
+
+
+ // Variables
+ Apn_Interface m_CameraInterface;
+
+ CApnCamData *m_ApnSensorInfo;
+
+ unsigned short m_RoiStartX, m_RoiStartY;
+ unsigned short m_RoiPixelsH, m_RoiPixelsV;
+ unsigned short m_RoiBinningH, m_RoiBinningV;
+
+ bool m_DigitizeOverscan;
+ Apn_Resolution m_DataBits;
+
+/* was private: */
+
+ // General helper functions
+ long LoadVerticalPattern();
+ long LoadClampPattern();
+ long LoadSkipPattern();
+ long LoadRoiPattern( unsigned short Binning );
+
+ long WriteHorizontalPattern( APN_HPATTERN_FILE *Pattern,
+ unsigned short reg,
+ unsigned short binning );
+
+ long InitTwelveBitAD();
+ long WriteTwelveBitOffset();
+
+ void UpdateGeneralStatus();
+
+ // Internal private variables
+ bool m_ResetVerticalArrays;
+
+ // Camera state variables
+ Apn_CameraMode m_pvtCameraMode;
+
+ Apn_NetworkMode m_pvtNetworkTransferMode;
+
+ unsigned short m_pvtImageCount;
+ unsigned short m_pvtTDIRows;
+ double m_pvtTDIRate;
+
+ double m_pvtSequenceDelay;
+ double m_pvtShutterStrobePosition;
+ double m_pvtShutterStrobePeriod;
+
+ unsigned short m_pvtExposurePixelsH, m_pvtExposurePixelsV;
+
+ unsigned short m_pvtTwelveBitGain;
+
+ Apn_LedMode m_pvtLedMode;
+ Apn_LedState m_pvtLedStateA;
+ Apn_LedState m_pvtLedStateB;
+
+ double m_pvtTestLedBrightness;
+
+ bool m_pvtCoolerEnable;
+ Apn_FanMode m_pvtFanMode;
+
+ double m_pvtCoolerBackoffPoint;
+
+ Apn_CoolerStatus m_pvtCoolerStatus;
+ Apn_Status m_pvtImagingStatus;
+ bool m_pvtShutterState;
+ bool m_pvtImageInProgress;
+ bool m_pvtImageReady;
+
+ unsigned short m_pvtStatusReg;
+
+ double m_pvtCoolerDrive;
+ double m_pvtCurrentHeatsinkTemp;
+ double m_pvtCurrentCcdTemp;
+
+ double m_pvtInputVoltage;
+ unsigned short m_pvtIoPortAssignment;
+ unsigned short m_pvtIoPortDirection;
+
+/* added USB/NET specifics */
+ unsigned short m_pvtBitsPerPixel;
+ unsigned short m_pvtWidth;
+ unsigned short m_pvtHeight;
+
+
+/* added sensor data mirrors */
+ bool sensorInfo();
+ char m_Sensor[20];
+ char m_CameraModel[20];
+ unsigned short m_CameraId;
+ bool m_InterlineCCD;
+ bool m_SupportsSerialA;
+ bool m_SupportsSerialB;
+ bool m_SensorTypeCCD;
+ unsigned short m_TotalColumns;
+ unsigned short m_ImagingColumns;
+ unsigned short m_ClampColumns;
+ unsigned short m_PreRoiSkipColumns;
+ unsigned short m_PostRoiSkipColumns;
+ unsigned short m_OverscanColumns;
+ unsigned short m_TotalRows;
+ unsigned short m_ImagingRows;
+ unsigned short m_UnderscanRows;
+ unsigned short m_OverscanRows;
+ unsigned short m_VFlushBinning;
+ bool m_HFlushDisable;
+ unsigned short m_ShutterCloseDelay;
+ double m_PixelSizeX;
+ double m_PixelSizeY;
+ bool m_Color;
+// double m_ReportedGainTwelveBit;
+ double m_ReportedGainSixteenBit;
+ double m_MinSuggestedExpTime;
+// unsigned short m_TempRegRate;
+ unsigned short m_TempRampRateOne;
+ unsigned short m_TempRampRateTwo;
+ unsigned short m_DefaultGainTwelveBit;
+ unsigned short m_DefaultOffsetTwelveBit;
+ unsigned short m_DefaultRVoltage;
+
+};
+
+#endif // !defined(AFX_APNCAMERA_H__CF513996_359F_4103_BBA6_2C730AE2C301__INCLUDED_)
+
+
+
+
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamera_Linux.cpp b/kstars/kstars/indi/apogee/ApnCamera_Linux.cpp
new file mode 100644
index 00000000..cce9ba37
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamera_Linux.cpp
@@ -0,0 +1,129 @@
+// ApnCamera.cpp: extras from the CCameraIO class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+
+#include "ApnCamera.h"
+#include "ApnCamTable.h"
+//#include "tcl.h"
+//#include "ccd.h"
+
+
+// Determine if camera is present
+// True if camera is present, false otherwise.
+bool CApnCamera::read_Present()
+{
+ // OutputDebugString( "read_Present()" );
+
+ USHORT ApStatus;
+ USHORT DatumA;
+ USHORT DatumB;
+ char szMsg[80];
+
+ DatumA = 0x0;
+ DatumB = 0x0;
+ ApStatus = 0;
+
+ Write( FPGA_REG_SCRATCH, 0x8086 );
+ Read( FPGA_REG_SCRATCH, DatumA );
+
+ Write( FPGA_REG_SCRATCH, 0x1F2F );
+ Read( FPGA_REG_SCRATCH, DatumB );
+
+ if ( (DatumA != 0x8086) || (DatumB != 0x1F2F) )
+ {
+ // OutputDebugString( "read_Present FAILED." );
+ sprintf( szMsg, "read_Present FAILED. DatumA: 0x%X DatumB: 0x%X", DatumA, DatumB );
+ // OutputDebugString( szMsg );
+ return false;
+ }
+
+ // OutputDebugString( "read_Present SUCCESS" );
+
+ return true;
+}
+
+bool CApnCamera::sensorInfo()
+{
+ strcpy(m_Sensor,m_ApnSensorInfo->m_Sensor);
+ strcpy(m_CameraModel,m_ApnSensorInfo->m_CameraModel);
+ m_CameraId = m_ApnSensorInfo->m_CameraId;
+ m_InterlineCCD = m_ApnSensorInfo->m_InterlineCCD;
+ m_SupportsSerialA = m_ApnSensorInfo->m_SupportsSerialA;
+ m_SupportsSerialB = m_ApnSensorInfo->m_SupportsSerialB;
+ m_SensorTypeCCD =m_ApnSensorInfo->m_SensorTypeCCD;
+ m_TotalColumns =m_ApnSensorInfo->m_TotalColumns;
+ m_ImagingColumns= m_ApnSensorInfo->m_ImagingColumns;
+ m_ClampColumns= m_ApnSensorInfo->m_ClampColumns;
+ m_PreRoiSkipColumns =m_ApnSensorInfo->m_PreRoiSkipColumns;
+ m_PostRoiSkipColumns= m_ApnSensorInfo->m_PostRoiSkipColumns;
+ m_OverscanColumns =m_ApnSensorInfo->m_OverscanColumns;
+ m_TotalRows =m_ApnSensorInfo->m_TotalRows;
+ m_ImagingRows =m_ApnSensorInfo->m_ImagingRows;
+ m_UnderscanRows= m_ApnSensorInfo->m_UnderscanRows;
+ m_OverscanRows =m_ApnSensorInfo->m_OverscanRows;
+ m_VFlushBinning =m_ApnSensorInfo->m_VFlushBinning;
+ m_HFlushDisable =m_ApnSensorInfo->m_HFlushDisable;
+ m_ShutterCloseDelay= m_ApnSensorInfo->m_ShutterCloseDelay;
+ m_PixelSizeX = m_ApnSensorInfo->m_PixelSizeX;
+ m_PixelSizeY = m_ApnSensorInfo->m_PixelSizeY;
+ m_Color = m_ApnSensorInfo->m_Color;
+// m_ReportedGainTwelveBit = m_ApnSensorInfo->m_ReportedGainTwelveBit;
+ m_ReportedGainSixteenBit= m_ApnSensorInfo->m_ReportedGainSixteenBit;
+ m_MinSuggestedExpTime = m_ApnSensorInfo->m_MinSuggestedExpTime;
+// m_TempRegRate =m_ApnSensorInfo->m_TempRegRate;
+ m_TempRampRateOne =m_ApnSensorInfo->m_TempRampRateOne;
+ m_TempRampRateTwo =m_ApnSensorInfo->m_TempRampRateTwo;
+ m_DefaultGainTwelveBit =m_ApnSensorInfo->m_DefaultGainTwelveBit;
+ m_DefaultOffsetTwelveBit= m_ApnSensorInfo->m_DefaultOffsetTwelveBit;
+ m_DefaultRVoltage =m_ApnSensorInfo->m_DefaultRVoltage;
+ return true;
+
+}
+
+#if 0
+bool CApnCamera::BufferImage(char *bufferName )
+{
+ unsigned short *pImageData;
+ bool status;
+ short cols,rows,hbin,vbin;
+ unsigned short xSize, ySize;
+ unsigned long count;
+
+ cols = m_pvtExposurePixelsH;
+ rows = m_pvtExposurePixelsV;
+
+ /* ALTA code has already applied binning calculations*/
+ hbin = 1;
+ vbin = 1;
+
+ pImageData = (unsigned short *)CCD_locate_buffer(bufferName, 2 , cols, rows, hbin, vbin );
+ if (pImageData == NULL) {
+ return 0;
+ }
+
+ status = GetImageData(pImageData, xSize, ySize, count);
+ return status;
+}
+
+
+
+bool CApnCamera::BufferDriftScan(char *bufferName, int delay, int rowCount, int nblock , int npipe)
+{
+ unsigned short *pImageData, *ptr;
+ bool status;
+ int irow;
+ short cols,rows,hbin,vbin;
+
+ cols = m_pvtExposurePixelsH;
+ rows = rowCount;
+ hbin = m_RoiBinningH;
+ vbin = 1;
+ return 1;
+}
+
+#endif
+
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamera_NET.cpp b/kstars/kstars/indi/apogee/ApnCamera_NET.cpp
new file mode 100644
index 00000000..0f739121
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamera_NET.cpp
@@ -0,0 +1,275 @@
+// ApnCamera_NET.cpp: implementation of the CApnCamera_NET class.
+//
+// Copyright (c) 2003, 2004 Apogee Instruments, Inc.
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ApnCamera_NET.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "ApogeeNet.h"
+#include "ApogeeNetErr.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+
+
+bool CApnCamera::InitDriver( unsigned long CamIdA,
+ unsigned short CamIdB,
+ unsigned long Option )
+{
+ char Hostname[25];
+ BYTE ipAddr[4];
+ int init;
+
+ ipAddr[0] = (BYTE)(CamIdA & 0xFF);
+ ipAddr[1] = (BYTE)((CamIdA >> 8) & 0xFF);
+ ipAddr[2] = (BYTE)((CamIdA >> 16) & 0xFF);
+ ipAddr[3] = (BYTE)((CamIdA >> 24) & 0xFF);
+
+ sprintf( Hostname, "%u.%u.%u.%u:%u", ipAddr[3], ipAddr[2], ipAddr[1], ipAddr[0], CamIdB );
+
+ if ( ApnNetConnect( Hostname ) != APNET_SUCCESS )
+ {
+ return false;
+ }
+
+ m_CameraInterface = Apn_Interface_NET;
+
+ // Before trying to initialize, perform a simple loopback test
+ unsigned short RegData;
+ unsigned short NewRegData;
+
+ RegData = 0x5AA5;
+ if ( Write( FPGA_REG_SCRATCH, RegData ) != APNET_SUCCESS ) return false;
+ if ( Read( FPGA_REG_SCRATCH, NewRegData ) != APNET_SUCCESS ) return false;
+ if ( RegData != NewRegData ) return false;
+
+ RegData = 0xA55A;
+ if ( Write( FPGA_REG_SCRATCH, RegData ) != APNET_SUCCESS ) return false;
+ if ( Read( FPGA_REG_SCRATCH, NewRegData ) != APNET_SUCCESS ) return false;
+ if ( RegData != NewRegData ) return false;
+ printf("Loopback test successful - ALTA-E detected at %u.%u.%u.%u:%u\n", ipAddr[3], ipAddr[2], ipAddr[1], ipAddr[0]);
+
+ // The loopback test was successful. Proceed with initialization.
+ init = InitDefaults();
+ if ( init != 0 ) {
+ printf("Loopback test successful - InitDefaults FAILED\n");
+ return false;
+ }
+
+ printf("Loopback test successful - InitDefaults completed\n");
+ return true;
+}
+
+
+bool CApnCamera::CloseDriver()
+{
+ ApnNetClose();
+
+ return true;
+}
+
+
+bool CApnCamera::GetImageData( unsigned short *pImageBuffer,
+ unsigned short &Width,
+ unsigned short &Height,
+ unsigned long &Count )
+{
+ unsigned short Offset;
+ unsigned short *pTempBuffer;
+ long i, j;
+
+
+ // Make sure it is okay to get the image data
+ // The app *should* have done this on its own, but we have to make sure
+ while ( !ImageReady() )
+ {
+ Sleep( 50 );
+ read_ImagingStatus();
+ }
+
+ Width = m_pvtWidth;
+ Height = m_pvtHeight;
+
+ if ( m_pvtBitsPerPixel == 16 )
+ Offset = 1;
+
+ if ( m_pvtBitsPerPixel == 12 )
+ Offset = 10;
+
+ Width -= Offset; // Calculate the true image width
+
+ pTempBuffer = new unsigned short[(Width+Offset) * Height];
+
+ ApnNetGetImageTcp( pTempBuffer );
+
+ for ( i=0; i<Height; i++ )
+ {
+ for ( j=0; j<Width; j++ )
+ {
+ pImageBuffer[(i*Width)+j] = pTempBuffer[(i*(Width+Offset))+j+Offset];
+ }
+ }
+
+ delete [] pTempBuffer;
+
+ Count = read_ImageCount();
+
+ SignalImagingDone();
+
+ return true;
+}
+
+
+bool CApnCamera::GetLineData( unsigned short *pLineBuffer,
+ unsigned short &Size )
+{
+ Size = 0;
+
+ return false;
+}
+
+
+long CApnCamera::PreStartExpose( unsigned short BitsPerPixel )
+{
+ m_pvtWidth = GetExposurePixelsH();
+ m_pvtHeight = GetExposurePixelsV();
+
+ if ( (BitsPerPixel != 16) && (BitsPerPixel != 12) )
+ {
+ // Invalid bit depth request
+ return 1;
+ }
+
+ m_pvtBitsPerPixel = BitsPerPixel;
+
+ if ( BitsPerPixel == 16 )
+ m_pvtWidth += 1;
+
+ if ( BitsPerPixel == 12 )
+ m_pvtWidth += 10;
+
+ if ( ApnNetStartExp( m_pvtWidth, m_pvtHeight ) != APNET_SUCCESS )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+long CApnCamera::PostStopExposure( bool DigitizeData )
+{
+ if ( ApnNetStopExp( DigitizeData ) != APNET_SUCCESS )
+ {
+ return 1;
+ }
+
+ if ( !DigitizeData )
+ {
+ SignalImagingDone();
+ }
+
+ return 0;
+}
+
+
+void CApnCamera::SetNetworkTransferMode( Apn_NetworkMode TransferMode )
+{
+ switch ( TransferMode )
+ {
+ case Apn_NetworkMode_Tcp:
+ ApnNetSetSpeed( false );
+ break;
+ case Apn_NetworkMode_Udp:
+ ApnNetSetSpeed( true );
+ break;
+ }
+}
+
+
+long CApnCamera::Read( unsigned short reg, unsigned short& val )
+{
+ if ( ApnNetReadReg( reg, &val ) != APNET_SUCCESS )
+ {
+ return 1; // Failure
+ }
+ return 0;
+}
+
+
+long CApnCamera::Write( unsigned short reg, unsigned short val )
+{
+ if ( ApnNetWriteReg( reg, val ) != APNET_SUCCESS )
+ {
+ return 1; // Failure
+ }
+
+ return 0;
+}
+
+
+long CApnCamera::WriteMultiSRMD( unsigned short reg, unsigned short val[], unsigned short count )
+{
+ if ( ApnNetWriteRegMulti( reg, val, count ) != APNET_SUCCESS )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+long CApnCamera::WriteMultiMRMD( unsigned short reg[], unsigned short val[], unsigned short count )
+{
+ if ( ApnNetWriteRegMultiMRMD( reg, val, count ) != APNET_SUCCESS )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+long CApnCamera::QueryStatusRegs( unsigned short& StatusReg,
+ unsigned short& HeatsinkTempReg,
+ unsigned short& CcdTempReg,
+ unsigned short& CoolerDriveReg,
+ unsigned short& VoltageReg,
+ unsigned short& TdiCounter,
+ unsigned short& SequenceCounter )
+{
+ unsigned short RegNumber[7];
+ unsigned short RegData[7];
+
+ RegNumber[0] = 91;
+ RegNumber[1] = 93;
+ RegNumber[2] = 94;
+ RegNumber[3] = 95;
+ RegNumber[4] = 96;
+ RegNumber[5] = 104;
+ RegNumber[6] = 105;
+
+ if ( ApnNetReadRegMulti( RegNumber, RegData, 7 ) != APNET_SUCCESS )
+ {
+ return 1;
+ }
+
+ StatusReg = RegData[0];
+ HeatsinkTempReg = RegData[1];
+ CcdTempReg = RegData[2];
+ CoolerDriveReg = RegData[3];
+ VoltageReg = RegData[4];
+ TdiCounter = RegData[5];
+ SequenceCounter = RegData[6];
+
+ return 0;
+}
+
diff --git a/kstars/kstars/indi/apogee/ApnCamera_NET.h b/kstars/kstars/indi/apogee/ApnCamera_NET.h
new file mode 100644
index 00000000..e46d3846
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamera_NET.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+// ApnCamera_NET.h: interface for the CApnCamera_NET class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_APNCAMERA_NET_H__D6F0E3AB_536C_4937_9E2B_DCF682D0DD31__INCLUDED_)
+#define AFX_APNCAMERA_NET_H__D6F0E3AB_536C_4937_9E2B_DCF682D0DD31__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "ApnCamera.h"
+
+class CApnCamera_NET : public CApnCamera
+{
+private:
+ unsigned short m_pvtBitsPerPixel;
+
+ unsigned short m_pvtWidth;
+ unsigned short m_pvtHeight;
+
+public:
+ CApnCamera_NET();
+ virtual ~CApnCamera_NET();
+
+ bool InitDriver( unsigned long CamIdA,
+ unsigned short CamIdB,
+ unsigned long Option );
+
+ bool CloseDriver();
+
+ long PreStartExpose( unsigned short BitsPerPixel );
+
+ long PostStopExposure( bool DigitizeData );
+
+
+ bool GetImageData( unsigned short *pImageData,
+ unsigned short &Width,
+ unsigned short &Height,
+ unsigned long &Count );
+
+ bool GetLineData( unsigned short *pLineBuffer,
+ unsigned short &Size );
+
+ long Read( unsigned short reg, unsigned short& val );
+ long Write( unsigned short reg, unsigned short val );
+
+ long WriteMultiSRMD( unsigned short reg,
+ unsigned short val[],
+ unsigned short count );
+
+ long WriteMultiMRMD( unsigned short reg[],
+ unsigned short val[],
+ unsigned short count );
+
+ long QueryStatusRegs( unsigned short& StatusReg,
+ unsigned short& HeatsinkTempReg,
+ unsigned short& CcdTempReg,
+ unsigned short& CoolerDriveReg,
+ unsigned short& VoltageReg,
+ unsigned short& TdiCounter,
+ unsigned short& SequenceCounter );
+
+};
+
+#endif // !defined(AFX_APNCAMERA_NET_H__D6F0E3AB_536C_4937_9E2B_DCF682D0DD31__INCLUDED_)
diff --git a/kstars/kstars/indi/apogee/ApnCamera_USB.cpp b/kstars/kstars/indi/apogee/ApnCamera_USB.cpp
new file mode 100644
index 00000000..a6bbad42
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamera_USB.cpp
@@ -0,0 +1,256 @@
+// ApnCamera_USB.cpp: implementation of the CApnCamera_USB class.
+//
+// Copyright (c) 2003, 2004 Apogee Instruments, Inc.
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "ApnCamera_USB.h"
+
+#include "ApogeeUsb.h"
+#include "ApogeeUsbErr.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+
+
+bool CApnCamera::InitDriver( unsigned long CamIdA,
+ unsigned short /*CamIdB*/,
+ unsigned long /*Option*/ )
+{
+ if ( ApnUsbOpen( (unsigned short)CamIdA ) != APN_USB_SUCCESS )
+ {
+ return false;
+ }
+
+ m_CameraInterface = Apn_Interface_USB;
+
+ // Before trying to initialize, perform a simple loopback test
+ unsigned short RegData;
+ unsigned short NewRegData;
+
+ RegData = 0x5AA5;
+ if ( Write( FPGA_REG_SCRATCH, RegData ) != APN_USB_SUCCESS ) return false;
+ if ( Read( FPGA_REG_SCRATCH, NewRegData ) != APN_USB_SUCCESS ) return false;
+ if ( RegData != NewRegData ) return false;
+
+ RegData = 0xA55A;
+ if ( Write( FPGA_REG_SCRATCH, RegData ) != APN_USB_SUCCESS ) return false;
+ if ( Read( FPGA_REG_SCRATCH, NewRegData ) != APN_USB_SUCCESS ) return false;
+ if ( RegData != NewRegData ) return false;
+
+ // The loopback test was successful. Proceed with initialization.
+ if ( InitDefaults() != 0 )
+ return false;
+
+ return true;
+}
+
+
+bool CApnCamera::CloseDriver()
+{
+ ApnUsbClose();
+
+ return true;
+}
+
+void CApnCamera::SetNetworkTransferMode( Apn_NetworkMode /*TransferMode*/ )
+{
+ return;
+}
+
+bool CApnCamera::GetImageData( unsigned short *pImageBuffer,
+ unsigned short &Width,
+ unsigned short &Height,
+ unsigned long &Count )
+{
+ unsigned short Offset(0);
+ unsigned short *pTempBuffer;
+ long i, j;
+
+
+ // Make sure it is okay to get the image data
+ // The app *should* have done this on its own, but we have to make sure
+ while ( !ImageReady() )
+ {
+ Sleep( 50 );
+ read_ImagingStatus();
+ }
+
+ Width = m_pvtWidth;
+ Height = m_pvtHeight;
+
+ if ( m_pvtBitsPerPixel == 16 )
+ Offset = 1;
+
+ if ( m_pvtBitsPerPixel == 12 )
+ Offset = 10;
+
+ Width -= Offset; // Calculate the true image width
+
+ pTempBuffer = new unsigned short[(Width+Offset) * Height];
+
+ ApnUsbGetImage( pTempBuffer );
+
+ for ( i=0; i<Height; i++ )
+ {
+ for ( j=0; j<Width; j++ )
+ {
+ pImageBuffer[(i*Width)+j] = pTempBuffer[(i*(Width+Offset))+j+Offset];
+ }
+ }
+
+ delete [] pTempBuffer;
+
+
+ Count = read_ImageCount();
+
+ SignalImagingDone();
+
+ return true;
+}
+
+
+bool CApnCamera::GetLineData( unsigned short */*pLineBuffer*/,
+ unsigned short &Size )
+{
+ Size = 0;
+
+ return false;
+}
+
+
+long CApnCamera::PreStartExpose( unsigned short BitsPerPixel )
+{
+ m_pvtWidth = GetExposurePixelsH();
+ m_pvtHeight = GetExposurePixelsV();
+
+ if ( (BitsPerPixel != 16) && (BitsPerPixel != 12) )
+ {
+ // Invalid bit depth request
+ return 1;
+ }
+
+ m_pvtBitsPerPixel = BitsPerPixel;
+
+
+ if ( BitsPerPixel == 16 )
+ m_pvtWidth += 1;
+
+ if ( BitsPerPixel == 12 )
+ m_pvtWidth += 10;
+
+ if ( ApnUsbStartExp( m_pvtWidth, m_pvtHeight ) != APN_USB_SUCCESS )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+long CApnCamera::PostStopExposure( bool DigitizeData )
+{
+ PUSHORT pRequestData;
+
+
+ if ( !DigitizeData )
+ {
+ while ( !ImageReady() )
+ {
+ Sleep( 50 );
+ read_ImagingStatus();
+ }
+
+ pRequestData = new USHORT[m_pvtWidth*m_pvtHeight];
+
+ ApnUsbGetImage( pRequestData );
+
+ delete [] pRequestData;
+
+ SignalImagingDone();
+ }
+
+ // The following code will eventually be the implementation of the STOP
+ // command for USB. Currently, this does not work correctly.
+ // if ( ApnUsbStopExp( DigitizeData ) != APN_USB_SUCCESS )
+ // {
+ // return 1;
+ // }
+
+ return 0;
+}
+
+
+long CApnCamera::Read( unsigned short reg, unsigned short& val )
+{
+ if ( ApnUsbReadReg( reg, &val ) != APN_USB_SUCCESS )
+ {
+ return 1; // Failure
+ }
+
+ return 0;
+}
+
+
+long CApnCamera::Write( unsigned short reg, unsigned short val )
+{
+ if ( ApnUsbWriteReg( reg, val ) != APN_USB_SUCCESS )
+ {
+ return 1; // Failure
+ }
+
+ return 0;
+}
+
+
+long CApnCamera::WriteMultiSRMD( unsigned short reg, unsigned short val[], unsigned short count )
+{
+ if ( ApnUsbWriteRegMulti( reg, val, count ) != APN_USB_SUCCESS )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+long CApnCamera::WriteMultiMRMD( unsigned short reg[], unsigned short val[], unsigned short count )
+{
+ if ( ApnUsbWriteRegMultiMRMD( reg, val, count ) != APN_USB_SUCCESS )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+long CApnCamera::QueryStatusRegs( unsigned short& StatusReg,
+ unsigned short& HeatsinkTempReg,
+ unsigned short& CcdTempReg,
+ unsigned short& CoolerDriveReg,
+ unsigned short& VoltageReg,
+ unsigned short& TdiCounter,
+ unsigned short& SequenceCounter )
+{
+ /*unsigned short stat,heat,ccdt,cool,volt,tdic,sequ;*/
+
+ if ( ApnUsbReadStatusRegs( &StatusReg,
+ &HeatsinkTempReg,
+ &CcdTempReg,
+ &CoolerDriveReg,
+ &VoltageReg,
+ &TdiCounter,
+ &SequenceCounter ) != APN_USB_SUCCESS )
+ {
+ return 1;
+ }
+ return 0;
+}
+
+
+
+
diff --git a/kstars/kstars/indi/apogee/ApnCamera_USB.h b/kstars/kstars/indi/apogee/ApnCamera_USB.h
new file mode 100644
index 00000000..0d4a3d07
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnCamera_USB.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+// ApnCamera_USB.h: interface for the CApnCamera_USB class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_APNCAMERA_USB_H__E83248CA_F0AA_4221_8E10_22FA70CEFAA6__INCLUDED_)
+#define AFX_APNCAMERA_USB_H__E83248CA_F0AA_4221_8E10_22FA70CEFAA6__INCLUDED_
+
+#include "ApnCamera.h"
+
+class CApnCamera_USB : public CApnCamera
+{
+private:
+ unsigned short m_pvtBitsPerPixel;
+
+ unsigned short m_pvtWidth;
+ unsigned short m_pvtHeight;
+
+public:
+ CApnCamera_USB();
+ virtual ~CApnCamera_USB();
+
+ bool InitDriver( unsigned long CamIdA,
+ unsigned short CamIdB,
+ unsigned long Option );
+
+ bool CloseDriver();
+
+ long PreStartExpose( unsigned short BitsPerPixel );
+
+ long PostStopExposure( bool DigitizeData );
+
+ bool GetImageData( unsigned short *pImageData,
+ unsigned short &Width,
+ unsigned short &Height,
+ unsigned long &Count );
+
+ bool GetLineData( unsigned short *pLineBuffer,
+ unsigned short &Size );
+
+ long Read( unsigned short reg, unsigned short& val );
+ long Write( unsigned short reg, unsigned short val );
+
+ long WriteMultiSRMD( unsigned short reg,
+ unsigned short val[],
+ unsigned short count );
+
+ long WriteMultiMRMD( unsigned short reg[],
+ unsigned short val[],
+ unsigned short count );
+
+ long QueryStatusRegs( unsigned short& StatusReg,
+ unsigned short& HeatsinkTempReg,
+ unsigned short& CcdTempReg,
+ unsigned short& CoolerDriveReg,
+ unsigned short& VoltageReg,
+ unsigned short& TdiCounter,
+ unsigned short& SequenceCounter );
+
+};
+
+#endif // !defined(AFX_APNCAMERA_USB_H__E83248CA_F0AA_4221_8E10_22FA70CEFAA6__INCLUDED_)
diff --git a/kstars/kstars/indi/apogee/ApnSerial.cpp b/kstars/kstars/indi/apogee/ApnSerial.cpp
new file mode 100644
index 00000000..43687aad
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnSerial.cpp
@@ -0,0 +1,27 @@
+// ApnSerial.cpp: implementation of the CApnSerial class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "apogee.h"
+#include "ApnSerial.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CApnSerial::CApnSerial()
+{
+ m_SerialId = -1;
+}
+
+CApnSerial::~CApnSerial()
+{
+
+}
diff --git a/kstars/kstars/indi/apogee/ApnSerial.h b/kstars/kstars/indi/apogee/ApnSerial.h
new file mode 100644
index 00000000..81179901
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnSerial.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+// ApnSerial.h: interface for the CApnSerial class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_APNSERIAL_H__A27F1749_FA8F_40E8_A03F_4A28C8378DD1__INCLUDED_)
+#define AFX_APNSERIAL_H__A27F1749_FA8F_40E8_A03F_4A28C8378DD1__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "Apogee.h"
+
+
+class CApnSerial
+{
+public:
+
+ CApnSerial();
+ virtual ~CApnSerial();
+
+ virtual bool InitPort( unsigned long CamIdA,
+ unsigned short CamIdB,
+ unsigned short SerialId ) = 0;
+
+ virtual bool ClosePort() = 0;
+
+ virtual bool GetBaudRate( unsigned long *BaudRate ) = 0;
+
+ virtual bool SetBaudRate( unsigned long BaudRate ) = 0;
+
+ virtual bool GetFlowControl( Apn_SerialFlowControl *FlowControl ) = 0;
+
+ virtual bool SetFlowControl( Apn_SerialFlowControl FlowControl ) = 0;
+
+ virtual bool GetParity( Apn_SerialParity *Parity ) = 0;
+
+ virtual bool SetParity( Apn_SerialParity Parity ) = 0;
+
+ virtual bool Read( char *ReadBuffer,
+ unsigned short *ReadCount ) = 0;
+
+ virtual bool Write( char *WriteBuffer,
+ unsigned short WriteCount ) = 0;
+
+ // Variables
+ Apn_Interface m_CameraInterface;
+ short m_SerialId;
+
+};
+
+#endif // !defined(AFX_APNSERIAL_H__A27F1749_FA8F_40E8_A03F_4A28C8378DD1__INCLUDED_)
diff --git a/kstars/kstars/indi/apogee/ApnSerial_NET.cpp b/kstars/kstars/indi/apogee/ApnSerial_NET.cpp
new file mode 100644
index 00000000..ded34f47
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnSerial_NET.cpp
@@ -0,0 +1,214 @@
+// ApnSerial_NET.cpp: implementation of the CApnSerial_NET class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "apogee.h"
+#include "ApnSerial_NET.h"
+
+#include "ApogeeNet.h"
+#include "ApogeeNetErr.h"
+
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CApnSerial_NET::CApnSerial_NET()
+{
+ m_SerialId = -1;
+}
+
+CApnSerial_NET::~CApnSerial_NET()
+{
+
+}
+
+bool CApnSerial_NET::InitPort( unsigned long CamIdA,
+ unsigned short CamIdB,
+ unsigned short SerialId )
+{
+ char Hostname[25];
+ BYTE ipAddr[4];
+
+
+ ipAddr[0] = (BYTE)(CamIdA & 0xFF);
+ ipAddr[1] = (BYTE)((CamIdA >> 8) & 0xFF);
+ ipAddr[2] = (BYTE)((CamIdA >> 16) & 0xFF);
+ ipAddr[3] = (BYTE)((CamIdA >> 24) & 0xFF);
+
+ sprintf( Hostname, "%u.%u.%u.%u", ipAddr[3], ipAddr[2], ipAddr[1], ipAddr[0] );
+
+ if ( m_SerialId != -1 )
+ {
+ return false;
+ }
+
+ if ( (SerialId != 0) && (SerialId != 1) )
+ {
+ return false;
+ }
+
+ if ( ApnNetStartSockets() != APNET_SUCCESS )
+ return false;
+
+ if ( ApnNetSerialPortOpen( Hostname, CamIdB, SerialId ) != APNET_SUCCESS )
+ return false;
+
+ m_SerialId = SerialId;
+
+ return true;
+}
+
+bool CApnSerial_NET::ClosePort()
+{
+ if ( m_SerialId == -1 )
+ return false;
+
+ // just close the port and not care whether it was successful. if it was,
+ // great. if not, we'll still set m_SerialId to -1 so that another call
+ // can at least be tried to connect to the port.
+ ApnNetSerialPortClose( m_SerialId );
+
+ ApnNetStopSockets();
+
+ m_SerialId = -1;
+
+ return true;
+}
+
+bool CApnSerial_NET::GetBaudRate( unsigned long *BaudRate )
+{
+ *BaudRate = -1;
+
+ if ( m_SerialId == -1 )
+ return false;
+
+ /*
+ unsigned long BaudRateRead;
+
+
+ if ( m_SerialId == -1 )
+ return false;
+
+ if ( ApnNetSerialReadBaudRate(m_SerialId, &BaudRateRead) != APNET_SUCCESS )
+ return false;
+
+ *BaudRate = BaudRateRead;
+ */
+
+ return true;
+}
+
+bool CApnSerial_NET::SetBaudRate( unsigned long BaudRate )
+{
+ if ( m_SerialId == -1 )
+ return false;
+
+ /*
+ if ( ApnNetSerialWriteBaudRate(m_SerialId, BaudRate) != APNET_SUCCESS )
+ return false;
+ */
+
+ return true;
+}
+
+bool CApnSerial_NET::GetFlowControl( Apn_SerialFlowControl *FlowControl )
+{
+ *FlowControl = Apn_SerialFlowControl_Unknown;
+
+ if ( m_SerialId == -1 )
+ return false;
+
+ /*
+ bool FlowControlRead;
+
+ if ( m_SerialId == -1 )
+ return false;
+
+ if ( ApnNetSerialReadFlowControl(m_SerialId, &FlowControlRead) != APNET_SUCCESS )
+ return false;
+ */
+
+ return true;
+}
+
+bool CApnSerial_NET::SetFlowControl( Apn_SerialFlowControl FlowControl )
+{
+ if ( m_SerialId == -1 )
+ return false;
+
+ /*
+ if ( ApnNetSerialWriteFlowControl(m_SerialId, FlowControl) != APNET_SUCCESS )
+ return false;
+ */
+
+ return true;
+}
+
+bool CApnSerial_NET::GetParity( Apn_SerialParity *Parity )
+{
+ *Parity = Apn_SerialParity_Unknown;
+
+ if ( m_SerialId == -1 )
+ return false;
+
+ /*
+ ApnNetParity ParityRead;
+
+ if ( m_SerialId == -1 )
+ return false;
+
+ if ( ApnNetSerialReadParity(m_SerialId, &ParityRead) != APNET_SUCCESS )
+ return false;
+
+ *Parity = (Apn_SerialParity)ParityRead;
+ */
+
+ return true;
+}
+
+bool CApnSerial_NET::SetParity( Apn_SerialParity Parity )
+{
+ if ( m_SerialId == -1 )
+ return false;
+
+ /*
+ if ( ApnNetSerialWriteParity(m_SerialId, (ApnNetParity)Parity) != APNET_SUCCESS )
+ return false;
+ */
+
+ return true;
+}
+
+bool CApnSerial_NET::Read( char *ReadBuffer, unsigned short *ReadCount )
+{
+ if ( m_SerialId == -1 )
+ return false;
+
+ if ( ApnNetSerialRead(m_SerialId, ReadBuffer, ReadCount) != APNET_SUCCESS )
+ {
+ *ReadCount = 0;
+ return false;
+ }
+
+ return true;
+}
+
+bool CApnSerial_NET::Write( char *WriteBuffer, unsigned short WriteCount )
+{
+ if ( m_SerialId == -1 )
+ return false;
+
+ if ( ApnNetSerialWrite(m_SerialId, WriteBuffer, WriteCount) != APNET_SUCCESS )
+ return false;
+
+ return true;
+}
+
diff --git a/kstars/kstars/indi/apogee/ApnSerial_NET.h b/kstars/kstars/indi/apogee/ApnSerial_NET.h
new file mode 100644
index 00000000..d7bc9745
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnSerial_NET.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+// ApnSerial_NET.h: interface for the CApnSerial_NET class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_APNSERIAL_NET_H__F31A372D_2B82_4998_B74C_FFAD8E3EEE86__INCLUDED_)
+#define AFX_APNSERIAL_NET_H__F31A372D_2B82_4998_B74C_FFAD8E3EEE86__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "ApnSerial.h"
+
+
+class CApnSerial_NET : public CApnSerial
+{
+public:
+ CApnSerial_NET();
+ virtual ~CApnSerial_NET();
+
+ bool InitPort( unsigned long CamIdA,
+ unsigned short CamIdB,
+ unsigned short SerialId );
+
+ bool ClosePort();
+
+ bool GetBaudRate( unsigned long *BaudRate );
+ bool SetBaudRate( unsigned long BaudRate );
+
+ bool GetFlowControl( Apn_SerialFlowControl *FlowControl );
+ bool SetFlowControl( Apn_SerialFlowControl FlowControl );
+
+ bool GetParity( Apn_SerialParity *Parity );
+ bool SetParity( Apn_SerialParity Parity );
+
+ bool Read( char *ReadBuffer,
+ unsigned short *ReadCount );
+
+ bool Write( char *WriteBuffer,
+ unsigned short WriteCount );
+
+};
+
+#endif // !defined(AFX_APNSERIAL_NET_H__F31A372D_2B82_4998_B74C_FFAD8E3EEE86__INCLUDED_)
diff --git a/kstars/kstars/indi/apogee/ApnSerial_USB.cpp b/kstars/kstars/indi/apogee/ApnSerial_USB.cpp
new file mode 100644
index 00000000..6effe609
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnSerial_USB.cpp
@@ -0,0 +1,79 @@
+// ApnSerial_USB.cpp: implementation of the CApnSerial_USB class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "apogee.h"
+#include "ApnSerial_USB.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CApnSerial_USB::CApnSerial_USB()
+{
+
+}
+
+CApnSerial_USB::~CApnSerial_USB()
+{
+
+}
+
+bool CApnSerial_USB::InitPort( unsigned long CamIdA,
+ unsigned short CamIdB,
+ unsigned short SerialId )
+{
+ return true;
+}
+
+bool CApnSerial_USB::ClosePort()
+{
+ return true;
+}
+
+bool CApnSerial_USB::GetBaudRate( unsigned long *BaudRate )
+{
+ return true;
+}
+
+bool CApnSerial_USB::SetBaudRate( unsigned long BaudRate )
+{
+ return true;
+}
+
+bool CApnSerial_USB::GetFlowControl( Apn_SerialFlowControl *FlowControl )
+{
+ return true;
+}
+
+bool CApnSerial_USB::SetFlowControl( Apn_SerialFlowControl FlowControl )
+{
+ return true;
+}
+
+bool CApnSerial_USB::GetParity( Apn_SerialParity *Parity )
+{
+ return true;
+}
+
+bool CApnSerial_USB::SetParity( Apn_SerialParity Parity )
+{
+ return true;
+}
+
+bool CApnSerial_USB::Read( char *ReadBuffer, unsigned short *ReadCount )
+{
+ return true;
+}
+
+bool CApnSerial_USB::Write( char *WriteBuffer, unsigned short WriteCount )
+{
+ return true;
+}
diff --git a/kstars/kstars/indi/apogee/ApnSerial_USB.h b/kstars/kstars/indi/apogee/ApnSerial_USB.h
new file mode 100644
index 00000000..cd10d9b5
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnSerial_USB.h
@@ -0,0 +1,43 @@
+// ApnSerial_USB.h: interface for the CApnSerial_USB class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_APNSERIAL_USB_H__D7A1A328_6505_438F_BCCE_FA3F3B5EECC2__INCLUDED_)
+#define AFX_APNSERIAL_USB_H__D7A1A328_6505_438F_BCCE_FA3F3B5EECC2__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "ApnSerial.h"
+
+class CApnSerial_USB : public CApnSerial
+{
+public:
+ CApnSerial_USB();
+ virtual ~CApnSerial_USB();
+
+ bool InitPort( unsigned long CamIdA,
+ unsigned short CamIdB,
+ unsigned short SerialId );
+
+ bool ClosePort();
+
+ bool GetBaudRate( unsigned long *BaudRate );
+ bool SetBaudRate( unsigned long BaudRate );
+
+ bool GetFlowControl( Apn_SerialFlowControl *FlowControl );
+ bool SetFlowControl( Apn_SerialFlowControl FlowControl );
+
+ bool GetParity( Apn_SerialParity *Parity );
+ bool SetParity( Apn_SerialParity Parity );
+
+ bool Read( char *ReadBuffer,
+ unsigned short *ReadCount );
+
+ bool Write( char *WriteBuffer,
+ unsigned short WriteCount );
+
+};
+
+#endif // !defined(AFX_APNSERIAL_USB_H__D7A1A328_6505_438F_BCCE_FA3F3B5EECC2__INCLUDED_)
diff --git a/kstars/kstars/indi/apogee/ApnUsbSys.h b/kstars/kstars/indi/apogee/ApnUsbSys.h
new file mode 100644
index 00000000..6016c9f6
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApnUsbSys.h
@@ -0,0 +1,46 @@
+// ApnUsbSys.h
+//
+// Copyright (c) 2003, 2004 Apogee Instruments, Inc.
+//
+// Defines common data structure(s) for sharing between application
+// layer and the ApUSB.sys device driver.
+//
+
+#if !defined(_APNUSBSYS_H__INCLUDED_)
+#define _APNUSBSYS_H__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+
+
+#define VND_ANCHOR_LOAD_INTERNAL 0xA0
+
+#define VND_APOGEE_CMD_BASE 0xC0
+#define VND_APOGEE_STATUS ( VND_APOGEE_CMD_BASE + 0x0 )
+#define VND_APOGEE_CAMCON_REG ( VND_APOGEE_CMD_BASE + 0x2 )
+#define VND_APOGEE_BUFCON_REG ( VND_APOGEE_CMD_BASE + 0x3 )
+#define VND_APOGEE_SET_SERIAL ( VND_APOGEE_CMD_BASE + 0x4 )
+#define VND_APOGEE_SERIAL ( VND_APOGEE_CMD_BASE + 0x5 )
+#define VND_APOGEE_EEPROM ( VND_APOGEE_CMD_BASE + 0x6 )
+#define VND_APOGEE_SOFT_RESET ( VND_APOGEE_CMD_BASE + 0x8 )
+#define VND_APOGEE_GET_IMAGE ( VND_APOGEE_CMD_BASE + 0x9 )
+#define VND_APOGEE_STOP_IMAGE ( VND_APOGEE_CMD_BASE + 0xA )
+
+
+#define REQUEST_IN 0x1
+#define REQUEST_OUT 0x0
+
+
+typedef struct _APN_USB_REQUEST
+{
+ unsigned char Request;
+ unsigned char Direction;
+ unsigned short Value;
+ unsigned short Index;
+} APN_USB_REQUEST, *PAPN_USB_REQUEST;
+
+
+
+#endif // !defined(_APNUSBSYS_H__INCLUDED_)
diff --git a/kstars/kstars/indi/apogee/Apogee.h b/kstars/kstars/indi/apogee/Apogee.h
new file mode 100644
index 00000000..d97740b2
--- /dev/null
+++ b/kstars/kstars/indi/apogee/Apogee.h
@@ -0,0 +1,97 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#if !defined(AFX_APOGEE__INCLUDED_)
+#define AFX_APOGEE__INCLUDED_
+
+
+#define Apn_Interface int
+#define Apn_Interface_NET 0
+#define Apn_Interface_USB 1
+
+#define Apn_NetworkMode int
+#define Apn_NetworkMode_Tcp 0
+#define Apn_NetworkMode_Udp 1
+
+#define Apn_Resolution int
+#define Apn_Resolution_SixteenBit 0
+#define Apn_Resolution_TwelveBit 1
+
+#define Apn_CameraMode int
+#define Apn_CameraMode_Normal 0
+#define Apn_CameraMode_TDI 1
+#define Apn_CameraMode_Test 2
+#define Apn_CameraMode_ExternalTrigger 3
+#define Apn_CameraMode_ExternalShutter 4
+
+#define Apn_Status int
+#define Apn_Status_DataError -2
+#define Apn_Status_PatternError -1
+#define Apn_Status_Idle 0
+#define Apn_Status_Exposing 1
+#define Apn_Status_ImagingActive 2
+#define Apn_Status_ImageReady 3
+#define Apn_Status_Flushing 4
+#define Apn_Status_WaitingOnTrigger 5
+
+#define Apn_LedMode int
+#define Apn_LedMode_DisableAll 0
+#define Apn_LedMode_DisableWhileExpose 1
+#define Apn_LedMode_EnableAll 2
+
+#define Apn_LedState int
+#define Apn_LedState_Expose 0
+#define Apn_LedState_ImageActive 1
+#define Apn_LedState_Flushing 2
+#define Apn_LedState_ExtTriggerWaiting 3
+#define Apn_LedState_ExtTriggerReceived 4
+#define Apn_LedState_ExtShutterInput 5
+#define Apn_LedState_ExtStartReadout 6
+#define Apn_LedState_AtTemp 7
+
+#define Apn_CoolerStatus int
+#define Apn_CoolerStatus_Off 0
+#define Apn_CoolerStatus_RampingToSetPoint 1
+#define Apn_CoolerStatus_AtSetPoint 2
+#define Apn_CoolerStatus_Revision 3
+
+#define Apn_FanMode int
+#define Apn_FanMode_Off 0
+#define Apn_FanMode_Low 1
+#define Apn_FanMode_Medium 2
+#define Apn_FanMode_High 3
+
+
+#define Camera_Status int
+#define Camera_Status_Idle 0
+#define Camera_Status_Waiting 1
+#define Camera_Status_Exposing 2
+#define Camera_Status_Downloading 3
+#define Camera_Status_LineReady 4
+#define Camera_Status_ImageReady 5
+#define Camera_Status_Flushing 6
+
+#define Camera_CoolerStatus int
+#define Camera_CoolerStatus_Off 0
+#define Camera_CoolerStatus_RampingToSetPoint 1
+#define Camera_CoolerStatus_Correcting 2
+#define Camera_CoolerStatus_RampingToAmbient 3
+#define Camera_CoolerStatus_AtAmbient 4
+#define Camera_CoolerStatus_AtMax 5
+#define Camera_CoolerStatus_AtMin 6
+#define Camera_CoolerStatus_AtSetPoint 7
+
+#define Camera_CoolerMode int
+#define Camera_CoolerMode_Off 0
+#define Camera_CoolerMode_On 1
+#define Camera_CoolerMode_Shutdown 2
+
+#endif
+
+
+
diff --git a/kstars/kstars/indi/apogee/ApogeeIoctl.h b/kstars/kstars/indi/apogee/ApogeeIoctl.h
new file mode 100644
index 00000000..ec0fc580
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApogeeIoctl.h
@@ -0,0 +1,40 @@
+// ApogeeIoctl.h Include file for I/O
+//
+// Copyright (c) 2000 Apogee Instruments Inc.
+//
+//Portions Copyright (c) 2000 The Random Factory.
+//
+// Define the IOCTL codes we will use. The IOCTL code contains a command
+// identifier, plus other information about the device, the type of access
+// with which the file must have been opened, and the type of buffering.
+//
+
+extern unsigned short apogee_bit;
+extern unsigned short apogee_word;
+extern unsigned long apogee_long;
+extern short apogee_signed;
+
+
+// General Ioctl definitions for Apogee CCD device driver
+
+#define APOGEE_IOC_MAGIC 'j'
+#define APOGEE_IOC_MAXNR 100
+#define APOGEE_IOCHARDRESET _IO(APOGEE_IOC_MAGIC,0)
+
+
+// Read single word
+#define IOCTL_GPD_READ_ISA_USHORT _IOR(APOGEE_IOC_MAGIC,1,apogee_word)
+
+// Write single word
+#define IOCTL_GPD_WRITE_ISA_USHORT _IOW(APOGEE_IOC_MAGIC,2,apogee_word)
+
+// Read line from camera
+#define IOCTL_GPD_READ_ISA_LINE _IOR(APOGEE_IOC_MAGIC,3,apogee_word)
+
+#define IOCTL_GPD_READ_PPI_USHORT _IOR(APOGEE_IOC_MAGIC,1,apogee_word)
+
+// Write single word
+#define IOCTL_GPD_WRITE_PPI_USHORT _IOW(APOGEE_IOC_MAGIC,2,apogee_word)
+
+// Read line from camera
+#define IOCTL_GPD_READ_PPI_LINE _IOR(APOGEE_IOC_MAGIC,3,apogee_word)
diff --git a/kstars/kstars/indi/apogee/ApogeeLinux.h b/kstars/kstars/indi/apogee/ApogeeLinux.h
new file mode 100644
index 00000000..d17e7bde
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApogeeLinux.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef APOGEELINUX_H
+#define APOGEELINUX_H
+
+#define APISA_READ_USHORT _IOR('a', 0x01, unsigned int)
+#define APISA_READ_LINE _IOR('a', 0x02, unsigned int)
+#define APISA_WRITE_USHORT _IOW('a', 0x03, unsigned int)
+
+#define APPPI_READ_USHORT _IOR('a', 0x01, unsigned int)
+#define APPPI_READ_LINE _IOR('a', 0x02, unsigned int)
+#define APPPI_WRITE_USHORT _IOW('a', 0x03, unsigned int)
+
+#define APPCI_READ_USHORT _IOR('a', 0x01, unsigned int)
+#define APPCI_READ_LINE _IOR('a', 0x02, unsigned int)
+#define APPCI_WRITE_USHORT _IOW('a', 0x03, unsigned int)
+
+#define APUSB_READ_USHORT _IOR('a', 0x01, unsigned int)
+#define APUSB_WRITE_USHORT _IOW('a', 0x02, unsigned int)
+#define APUSB_USB_STATUS _IOR('a', 0x03, unsigned int)
+#define APUSB_PRIME_USB_DOWNLOAD _IOR('a', 0x04, unsigned int)
+#define APUSB_STOP_USB_IMAGE _IOR('a', 0x05, unsigned int)
+#define APUSB_READ_USB_IMAGE _IOR('a', 0x06, unsigned int)
+#define APUSB_USB_RESET _IOR('a', 0x07, unsigned int)
+#define APUSB_READ_USB_SERIAL _IOR('a', 0x08, unsigned int)
+#define APUSB_WRITE_USB_SERIAL _IOR('a', 0x09, unsigned int)
+#define APUSB_USB_SET_SERIAL _IOR('a', 0x0A, unsigned int)
+#define APUSB_USB_REQUEST _IOR('a', 0x0B, unsigned int)
+#define APUSB_READ_STATUS _IOR('a', 0x0C, unsigned int)
+
+#define appci_major_number 60
+#define apppi_major_number 61
+#define apisa_major_number 62
+
+struct apIOparam // IOCTL data
+ {
+ unsigned int reg;
+ unsigned long param1, param2;
+ };
+
+#define APOGEE_PCI_DEVICE "/dev/appci"
+#define APOGEE_PPI_DEVICE "/dev/apppi"
+#define APOGEE_ISA_DEVICE "/dev/apisa"
+#define APOGEE_USB_DEVICE "/dev/usb/alta"
+
+#endif
diff --git a/kstars/kstars/indi/apogee/ApogeeUsb.h b/kstars/kstars/indi/apogee/ApogeeUsb.h
new file mode 100644
index 00000000..f242ea6a
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApogeeUsb.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#if !defined(_APOGEEUSB_H__INCLUDED_)
+#define _APOGEEUSB_H__INCLUDED_
+
+#ifndef APN_USB_TYPE
+#define APN_USB_TYPE unsigned short
+#endif
+
+#define APN_USB_MAXCAMERAS 255
+
+
+typedef struct _APN_USB_CAMINFO {
+ unsigned short CamNumber;
+ unsigned short CamModel;
+} APN_USB_CAMINFO;
+
+
+
+#ifndef IN
+#define IN
+#endif
+
+#ifndef OUT
+#define OUT
+#endif
+
+
+APN_USB_TYPE ApnUsbOpen( unsigned short DeviceNumber );
+
+
+APN_USB_TYPE ApnUsbClose( void );
+
+
+APN_USB_TYPE ApnUsbDiscovery( unsigned short *UsbCamCount,
+ APN_USB_CAMINFO UsbCamInfo[] );
+
+
+APN_USB_TYPE ApnUsbReadReg( unsigned short FpgaReg,
+ unsigned short *FpgaData );
+
+
+APN_USB_TYPE ApnUsbWriteReg( unsigned short FpgaReg,
+ unsigned short FpgaData );
+
+
+APN_USB_TYPE ApnUsbWriteRegMulti( unsigned short FpgaReg,
+ unsigned short FpgaData[],
+ unsigned short RegCount );
+
+
+APN_USB_TYPE ApnUsbWriteRegMultiMRMD( unsigned short FpgaReg[],
+ unsigned short FpgaData[],
+ unsigned short RegCount );
+
+
+APN_USB_TYPE ApnUsbReadStatusRegs( unsigned short *StatusReg,
+ unsigned short *HeatsinkTempReg,
+ unsigned short *CcdTempReg,
+ unsigned short *CoolerDriveReg,
+ unsigned short *VoltageReg,
+ unsigned short *TdiCounter,
+ unsigned short *SequenceCounter );
+
+
+APN_USB_TYPE ApnUsbStartExp( unsigned short ImageWidth,
+ unsigned short ImageHeight );
+
+
+APN_USB_TYPE ApnUsbStopExp( bool DigitizeData );
+
+
+APN_USB_TYPE ApnUsbGetImage( unsigned short *pMem );
+
+
+APN_USB_TYPE ApnUsbReset();
+
+
+#endif // !defined(_APOGEEUSB_H__INCLUDED_)
diff --git a/kstars/kstars/indi/apogee/ApogeeUsbErr.h b/kstars/kstars/indi/apogee/ApogeeUsbErr.h
new file mode 100644
index 00000000..69ee4d3a
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApogeeUsbErr.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+// Error codes for the ApogeeUsb* files
+
+
+#define APN_USB_SUCCESS 0
+
+#define APN_USB_ERR_OPEN 1
+#define APN_USB_ERR_READ 2
+#define APN_USB_ERR_WRITE 3
+
+#define APN_USB_ERR_IMAGE_DOWNLOAD 4
+
+#define APN_USB_ERR_START_EXP 5
+#define APN_USB_ERR_STOP_EXP 6
+
+#define APN_USB_ERR_STATUS 7
+
+#define APN_USB_ERR_RESET 8
+
+
+
+
diff --git a/kstars/kstars/indi/apogee/ApogeeUsbLinux.cpp b/kstars/kstars/indi/apogee/ApogeeUsbLinux.cpp
new file mode 100644
index 00000000..fcedd1d9
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApogeeUsbLinux.cpp
@@ -0,0 +1,394 @@
+// ApogeeUsb.cpp : Library of basic USB functions for Apogee APn/Alta.
+//
+
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <sched.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+
+#include <usb.h>
+#include "ApogeeUsb.h"
+#include "ApogeeUsbErr.h"
+#include "ApogeeLinux.h"
+
+
+#define HANDLE struct usb_dev_handle;
+#define ULONG unsigned int
+#define BOOLEAN unsigned int
+#define USHORT unsigned short
+
+#define APOGEE_USB_DEVICE "/dev/usb/alta"
+#define INVALID_HANDLE_VALUE -1
+
+#define VND_ANCHOR_LOAD_INTERNAL 0xA0
+#define VND_APOGEE_CMD_BASE 0xC0
+#define VND_APOGEE_STATUS ( VND_APOGEE_CMD_BASE + 0x0 )
+#define VND_APOGEE_CAMCON_REG ( VND_APOGEE_CMD_BASE + 0x2 )
+#define VND_APOGEE_BUFCON_REG ( VND_APOGEE_CMD_BASE + 0x3 )
+#define VND_APOGEE_SET_SERIAL ( VND_APOGEE_CMD_BASE + 0x4 )
+#define VND_APOGEE_SERIAL ( VND_APOGEE_CMD_BASE + 0x5 )
+#define VND_APOGEE_EEPROM ( VND_APOGEE_CMD_BASE + 0x6 )
+#define VND_APOGEE_SOFT_RESET ( VND_APOGEE_CMD_BASE + 0x8 )
+#define VND_APOGEE_GET_IMAGE ( VND_APOGEE_CMD_BASE + 0x9 )
+#define VND_APOGEE_STOP_IMAGE ( VND_APOGEE_CMD_BASE + 0xA )
+
+#define USB_ALTA_VENDOR_ID 0x125c
+#define USB_ALTA_PRODUCT_ID 0x0010
+#define USB_DIR_IN USB_ENDPOINT_IN
+#define USB_DIR_OUT USB_ENDPOINT_OUT
+
+
+// Global variables used in this DLL
+struct usb_dev_handle *g_hSysDriver;
+ULONG g_UsbImgSizeBytes;
+char controlBuffer[1024];
+
+#define IMAGE_BUFFER_SIZE 126976 // Number of requested bytes in a transfer
+//#define IMAGE_BUFFER_SIZE 253952 // Number of requested bytes in a transfer
+
+
+// This is an example of an exported function.
+APN_USB_TYPE ApnUsbOpen( unsigned short /*DevNumber*/ )
+{
+
+ /*char deviceName[128];*/
+ struct usb_bus *bus;
+ struct usb_device *dev;
+ struct usb_dev_handle *hDevice(NULL);
+
+ usb_init();
+
+ usb_find_busses();
+ usb_find_devices();
+
+ /*char string[256];*/
+
+ int found = 0;
+
+ /* find ALTA device */
+ for(bus = usb_busses; bus && !found; bus = bus->next) {
+ for(dev = bus->devices; dev && !found; dev = dev->next) {
+ if (dev->descriptor.idVendor == USB_ALTA_VENDOR_ID &&
+ dev->descriptor.idProduct == USB_ALTA_PRODUCT_ID) {
+ hDevice = usb_open(dev);
+// cerr << "Found ALTA USB. Attempting to open... ";
+ found = 1;
+ if (hDevice) {
+// if (!usb_get_string_simple(hDevice,
+// dev->descriptor.iSerialNumber,
+// string, sizeof(string)))
+// throw DevOpenError();
+// cerr << "Success.\n";
+// cerr << "Serial number: " << string << endl;
+ }
+ else return APN_USB_ERR_OPEN;
+ }
+ }
+ }
+
+ if (!found) return APN_USB_ERR_OPEN;
+// if (!usb_set_configuration(hDevice, 0x0)) return APN_USB_ERR_OPEN;
+ if (!usb_claim_interface(hDevice, 0x0)) return APN_USB_ERR_OPEN;
+
+ g_hSysDriver = hDevice;
+ g_UsbImgSizeBytes = 0;
+// printf("DRIVER: opened device\n");
+
+ return APN_USB_SUCCESS; // Success
+}
+
+
+APN_USB_TYPE ApnUsbClose( void )
+{
+
+ if ( g_hSysDriver != 0 )
+ {
+ usb_release_interface(g_hSysDriver, 0x0);
+ usb_close(g_hSysDriver);
+ g_hSysDriver = 0;
+ }
+
+ return APN_USB_SUCCESS; // Success
+}
+
+
+
+APN_USB_TYPE ApnUsbReadReg( unsigned short FpgaReg, unsigned short *FpgaData )
+{
+ int Success;
+ unsigned short RegData;
+
+ Success = usb_control_msg((struct usb_dev_handle *)g_hSysDriver,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, VND_APOGEE_CAMCON_REG,
+ FpgaReg, FpgaReg,(char *)&RegData, 2, 50);
+ *FpgaData = RegData;
+
+/* printf("DRIVER: usb read reg=%x data=%x s=%x\n",FpgaReg,*FpgaData,Success); */
+ if ( !Success )
+ return APN_USB_ERR_WRITE;
+ return APN_USB_SUCCESS; // Success
+}
+
+APN_USB_TYPE ApnUsbWriteReg( unsigned short FpgaReg, unsigned short FpgaData )
+{
+ char *cbuf;
+ int Success;
+
+ cbuf = (char *)&FpgaData;
+ Success = usb_control_msg((struct usb_dev_handle *)g_hSysDriver,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, VND_APOGEE_CAMCON_REG,
+ 0, FpgaReg, cbuf, 2, 50);
+/* printf("DRIVER: usb write reg=%x data=%x s=%x\n",FpgaReg,FpgaData,Success); */
+ if ( !Success )
+ return APN_USB_ERR_WRITE;
+ return APN_USB_SUCCESS; // Success
+
+
+}
+
+
+
+
+APN_USB_TYPE ApnUsbWriteRegMulti( unsigned short FpgaReg, unsigned short FpgaData[], unsigned short RegCount )
+{
+ unsigned short Counter;
+
+ for ( Counter=0; Counter<RegCount; Counter++ )
+ {
+ if ( ApnUsbWriteReg( FpgaReg, FpgaData[Counter] ) != APN_USB_SUCCESS )
+ {
+ return APN_USB_ERR_WRITE;
+ }
+ }
+
+ return APN_USB_SUCCESS; // Success
+}
+
+APN_USB_TYPE ApnUsbWriteRegMultiMRMD( unsigned short FpgaReg[],
+ unsigned short FpgaData[],
+ unsigned short RegCount )
+{
+ unsigned short Counter;
+
+ for ( Counter=0; Counter<RegCount; Counter++ )
+ {
+ if ( ApnUsbWriteReg( FpgaReg[Counter],
+ FpgaData[Counter] ) != APN_USB_SUCCESS )
+ {
+ return APN_USB_ERR_WRITE;
+ }
+ }
+
+ return APN_USB_SUCCESS;
+}
+
+
+APN_USB_TYPE ApnUsbReadStatusRegs( unsigned short *StatusReg,
+ unsigned short *HeatsinkTempReg,
+ unsigned short *CcdTempReg,
+ unsigned short *CoolerDriveReg,
+ unsigned short *VoltageReg,
+ unsigned short *TdiCounter,
+ unsigned short *SequenceCounter )
+{
+ BOOLEAN Success;
+ /*unsigned int BytesReceived;*/
+ unsigned short *Data;
+ unsigned char StatusData[21];
+
+ Success = usb_control_msg(g_hSysDriver,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, VND_APOGEE_STATUS,
+ 0, 0, (char *)&StatusData, 21, 3000);
+
+// if ( !Success )
+// return APN_USB_ERR_STATUS;
+ Data = (unsigned short *)StatusData;
+
+ *HeatsinkTempReg = Data[0];
+ *CcdTempReg = Data[1];
+ *CoolerDriveReg = Data[2];
+ *VoltageReg = Data[3];
+ *TdiCounter = Data[4];
+ *SequenceCounter = Data[5];
+ *StatusReg = Data[6];
+
+ if ( (StatusData[20] & 0x01) != 0 )
+ {
+ *StatusReg |= 0x8;
+ }
+
+ return APN_USB_SUCCESS;
+}
+
+
+APN_USB_TYPE ApnUsbStartExp( unsigned short ImageWidth,
+ unsigned short ImageHeight )
+{
+ BOOLEAN Success;
+ ULONG ImageSize;
+ unsigned short BytesReceived;
+
+
+// if ( (g_hSysDriver) == 0)
+// {
+// return APN_USB_ERR_OPEN;
+// }
+
+ g_UsbImgSizeBytes = ImageWidth * ImageHeight * 2;
+ ImageSize = ImageWidth * ImageHeight;
+
+ if ( g_UsbImgSizeBytes == 0 )
+ {
+ return APN_USB_ERR_START_EXP;
+ }
+
+ Success = usb_control_msg(g_hSysDriver,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, VND_APOGEE_GET_IMAGE,
+ (ImageSize >> 16) & 0xFFFF,
+ (ImageSize & 0xFFFF), (char *)&BytesReceived, 4, 3000);
+
+// printf("DRIVER: startexp s=%x\n",Success);
+
+// if ( !Success )
+// {
+// return APN_USB_ERR_START_EXP;
+// }
+
+ return APN_USB_SUCCESS;
+}
+
+
+APN_USB_TYPE ApnUsbStopExp( bool DigitizeData )
+{
+ BOOLEAN Success;
+ unsigned short BytesReceived;
+
+
+// if ( (g_hSysDriver) == 0)
+// {
+// return APN_USB_ERR_OPEN;
+// }
+
+ if ( DigitizeData == false )
+ {
+ Success = usb_control_msg(g_hSysDriver,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, VND_APOGEE_STOP_IMAGE,
+ 0, 0,(char *)&BytesReceived, 2, 3000);
+
+// if ( !Success )
+// {
+// return APN_USB_ERR_STOP_EXP;
+// }
+ }
+
+ return APN_USB_SUCCESS;
+}
+
+APN_USB_TYPE ApnUsbGetImage( unsigned short *pMem )
+{
+ BOOLEAN Success;
+ ULONG ImageBytesRemaining;
+ ULONG ReceivedSize;
+
+ Success = 1;
+// if ( (g_hSysDriver) == 0 )
+// {
+// return APN_USB_ERR_OPEN;
+// }
+
+ ImageBytesRemaining = g_UsbImgSizeBytes;
+
+
+ ////////////////////////
+ ULONG LoopCount = g_UsbImgSizeBytes / IMAGE_BUFFER_SIZE;
+ ULONG Remainder = g_UsbImgSizeBytes - ( LoopCount * IMAGE_BUFFER_SIZE );
+ ULONG MemIterator = IMAGE_BUFFER_SIZE / 2;
+ ULONG Counter;
+
+
+ for ( Counter=0; Counter<LoopCount; Counter++ )
+ {
+ ReceivedSize = usb_bulk_read(g_hSysDriver, 0x86,
+ (char *)pMem, IMAGE_BUFFER_SIZE, 1000);
+// printf("DRIVER: bulkread size=%x\n",ReceivedSize);
+
+ if ( ReceivedSize != IMAGE_BUFFER_SIZE )
+ {
+ Success = 0;
+ break;
+ }
+ else
+ {
+ pMem += MemIterator;
+ printf(".");
+ }
+ }
+
+ if ( Remainder != 0 )
+ {
+ ReceivedSize = usb_bulk_read(g_hSysDriver, 0x86,
+ (char *)pMem, Remainder, 1000);
+// printf("DRIVER: bulkread2 size=%x\n",ReceivedSize);
+
+ if ( ReceivedSize != Remainder )
+ Success = 0;
+ }
+ printf("\n");
+
+ if ( !Success )
+ return APN_USB_ERR_IMAGE_DOWNLOAD;
+
+ return APN_USB_SUCCESS; // Success
+}
+
+
+APN_USB_TYPE ApnUsbReset()
+{
+ BOOLEAN Success;
+ unsigned short BytesReceived;
+
+// if ( (g_hSysDriver) == 0)
+// {
+// return APN_USB_ERR_OPEN;
+// }
+
+ Success = usb_control_msg(g_hSysDriver,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, VND_APOGEE_SOFT_RESET,
+ 0, 0, (char *)&BytesReceived, 2, 3000);
+// printf("DRIVER: reset s=%x\n",Success);
+
+ if ( !Success )
+ {
+ return APN_USB_ERR_RESET;
+ }
+
+ return APN_USB_SUCCESS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/kstars/kstars/indi/apogee/ApogeeUsbLinuxForKernel.cpp b/kstars/kstars/indi/apogee/ApogeeUsbLinuxForKernel.cpp
new file mode 100644
index 00000000..4cbb77b2
--- /dev/null
+++ b/kstars/kstars/indi/apogee/ApogeeUsbLinuxForKernel.cpp
@@ -0,0 +1,486 @@
+// ApogeeUsb.cpp : Library of basic USB functions for Apogee APn/Alta.
+//
+
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <sched.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+
+#include "ApogeeUsb.h"
+#include "ApogeeUsbErr.h"
+#include "ApogeeLinux.h"
+
+
+#define HANDLE unsigned int
+#define ULONG unsigned int
+#define BOOLEAN unsigned int
+#define USHORT unsigned short
+
+#define APOGEE_USB_DEVICE "/dev/usb/alta"
+#define INVALID_HANDLE_VALUE -1
+
+
+// Global variables used in this DLL
+HANDLE g_hSysDriver;
+ULONG g_UsbImgSizeBytes;
+
+
+// 1044480
+// 520192
+// 126976
+// 61440
+// 49152
+// 4096
+#define IMAGE_BUFFER_SIZE 126976 // Number of requested bytes in a transfer
+//#define IMAGE_BUFFER_SIZE 253952 // Number of requested bytes in a transfer
+
+
+// This is an example of an exported function.
+APN_USB_TYPE ApnUsbOpen( unsigned short DevNumber )
+{
+
+ char deviceName[128];
+
+ g_hSysDriver = 0;
+ g_UsbImgSizeBytes = 0;
+
+ // Open the driver
+ sprintf(deviceName,"%s%d",APOGEE_USB_DEVICE,DevNumber);
+ g_hSysDriver = ::open(deviceName,O_RDONLY);
+
+ if ( g_hSysDriver == INVALID_HANDLE_VALUE )
+ {
+ return APN_USB_ERR_OPEN; // Failure to open device
+ }
+
+ return APN_USB_SUCCESS; // Success
+}
+
+
+APN_USB_TYPE ApnUsbClose( void )
+{
+ if ( (g_hSysDriver != INVALID_HANDLE_VALUE ) && (g_hSysDriver != 0) )
+ {
+ ::close( g_hSysDriver );
+ g_hSysDriver = 0;
+ }
+
+ return APN_USB_SUCCESS; // Success
+}
+
+
+APN_USB_TYPE ApnUsbDiscovery( unsigned short *UsbCamCount,
+ APN_USB_CAMINFO UsbCamInfo[] )
+{
+ HANDLE hDriver;
+ char deviceName[64];
+ unsigned short RegNumber;
+ unsigned short retval;
+ struct apIOparam request;
+ USHORT RegData;
+ *UsbCamCount = 0;
+
+
+ for ( int i=0; i<APN_USB_MAXCAMERAS; i++ )
+ {
+ NULL,
+ NULL,
+
+ // Open the driver
+ sprintf(deviceName,"%s%d",APOGEE_USB_DEVICE,i);
+ hDriver = ::open(deviceName,O_RDONLY);
+
+ if ( hDriver != INVALID_HANDLE_VALUE )
+ {
+ // first set the camera number
+ UsbCamInfo[*UsbCamCount].CamNumber = i;
+
+ // now determine the camera model with a read operation
+ BOOLEAN Success;
+ USHORT FpgaReg;
+ USHORT RegData;
+ ULONG BytesReceived;
+
+ FpgaReg = 100;
+ request.reg = FpgaReg;
+ request.param1=(unsigned long)&retval;
+ Success=ioctl(hDriver,APUSB_READ_USHORT,(unsigned long)&request);
+ RegData = (unsigned short)retval;
+
+ if ( Success )
+ {
+ UsbCamInfo[*UsbCamCount].CamModel = RegData & 0x00FF;
+ (*UsbCamCount)++;
+ }
+ }
+
+ }
+
+ return APN_USB_SUCCESS;
+}
+
+
+APN_USB_TYPE ApnUsbReadReg( unsigned short FpgaReg, unsigned short *FpgaData )
+{
+ BOOLEAN Success;
+ USHORT RegData;
+ unsigned short RegNumber;
+ unsigned short retval;
+ struct apIOparam request;
+
+ if ( (g_hSysDriver == INVALID_HANDLE_VALUE) || (g_hSysDriver == 0) )
+ {
+ return APN_USB_ERR_OPEN;
+ }
+
+
+ request.reg = FpgaReg;
+ request.param1=(unsigned long)&retval;
+ Success=ioctl(g_hSysDriver,APUSB_READ_USHORT,(unsigned long)&request);
+ RegData = (unsigned short)retval;
+
+ if ( (!Success) )
+ {
+ return APN_USB_ERR_READ;
+ }
+
+ *FpgaData = RegData;
+
+ return APN_USB_SUCCESS; // Success
+}
+
+
+APN_USB_TYPE ApnUsbWriteReg( unsigned short FpgaReg, unsigned short FpgaData )
+{
+ BOOLEAN Success;
+ unsigned short RegNumber;
+ struct apIOparam request;
+
+ if ( (g_hSysDriver == INVALID_HANDLE_VALUE) || (g_hSysDriver == 0) )
+ {
+ return APN_USB_ERR_OPEN;
+ }
+
+ request.reg = FpgaReg;
+ request.param1=(int)FpgaData;
+ Success=ioctl(g_hSysDriver,APUSB_WRITE_USHORT,(unsigned long)&request);
+ if ( !Success )
+ return APN_USB_ERR_WRITE;
+
+ return APN_USB_SUCCESS; // Success
+}
+
+
+APN_USB_TYPE ApnUsbWriteRegMulti( unsigned short FpgaReg, unsigned short FpgaData[], unsigned short RegCount )
+{
+ unsigned short Counter;
+
+ for ( Counter=0; Counter<RegCount; Counter++ )
+ {
+ if ( ApnUsbWriteReg( FpgaReg, FpgaData[Counter] ) != APN_USB_SUCCESS )
+ {
+ return APN_USB_ERR_WRITE;
+ }
+ }
+
+ return APN_USB_SUCCESS; // Success
+}
+
+APN_USB_TYPE ApnUsbWriteRegMultiMRMD( unsigned short FpgaReg[],
+ unsigned short FpgaData[],
+ unsigned short RegCount )
+{
+ unsigned short Counter;
+
+ for ( Counter=0; Counter<RegCount; Counter++ )
+ {
+ if ( ApnUsbWriteReg( FpgaReg[Counter], FpgaData[Counter] ) != APN_USB_SUCCESS )
+ {
+ return APN_USB_ERR_WRITE;
+ }
+ }
+
+ return APN_USB_SUCCESS;
+}
+
+
+APN_USB_TYPE ApnUsbReadStatusRegs( unsigned short *StatusReg,
+ unsigned short *HeatsinkTempReg,
+ unsigned short *CcdTempReg,
+ unsigned short *CoolerDriveReg,
+ unsigned short *VoltageReg,
+ unsigned short *TdiCounter,
+ unsigned short *SequenceCounter )
+{
+ BOOLEAN Success;
+ unsigned int BytesReceived;
+ unsigned short RegNumber;
+ struct apIOparam request;
+ unsigned short *Data;
+ unsigned char StatusData[21];
+
+ request.reg = 0; //check this *******************
+ request.param1=(unsigned long)&StatusData;
+ Success=ioctl(g_hSysDriver,APUSB_READ_STATUS,(unsigned long)&request);
+
+// if ( !Success )
+// return APN_USB_ERR_STATUS;
+ Data = (unsigned short *)StatusData;
+
+ *HeatsinkTempReg = Data[0];
+ *CcdTempReg = Data[1];
+ *CoolerDriveReg = Data[2];
+ *VoltageReg = Data[3];
+ *TdiCounter = Data[4];
+ *SequenceCounter = Data[5];
+ *StatusReg = Data[6];
+
+ if ( (StatusData[20] & 0x01) != 0 )
+ {
+ *StatusReg |= 0x8;
+ }
+
+ return APN_USB_SUCCESS;
+}
+
+
+APN_USB_TYPE ApnUsbStartExp( unsigned short ImageWidth,
+ unsigned short ImageHeight )
+{
+ BOOLEAN Success;
+ ULONG ImageSize;
+ ULONG BytesReceived;
+ unsigned short RegNumber;
+ struct apIOparam request;
+
+
+ if ( (g_hSysDriver == INVALID_HANDLE_VALUE) || (g_hSysDriver == 0) )
+ {
+ return APN_USB_ERR_OPEN;
+ }
+
+ g_UsbImgSizeBytes = ImageWidth * ImageHeight * 2;
+ ImageSize = ImageWidth * ImageHeight;
+
+ if ( g_UsbImgSizeBytes == 0 )
+ {
+ return APN_USB_ERR_START_EXP;
+ }
+
+ request.reg = (int)ImageSize;
+ request.param1= 0;
+ Success=ioctl(g_hSysDriver,APUSB_PRIME_USB_DOWNLOAD,(unsigned long)&request);
+
+ if ( !Success )
+ {
+ return APN_USB_ERR_START_EXP;
+ }
+
+ return APN_USB_SUCCESS;
+}
+
+
+APN_USB_TYPE ApnUsbStopExp( bool DigitizeData )
+{
+ BOOLEAN Success;
+ ULONG BytesReceived;
+ unsigned short RegNumber;
+ struct apIOparam request;
+
+
+ if ( (g_hSysDriver == INVALID_HANDLE_VALUE) || (g_hSysDriver == 0) )
+ {
+ return APN_USB_ERR_OPEN;
+ }
+
+ if ( DigitizeData == false )
+ {
+ request.reg = 0;
+ request.param1 = 0;
+ Success=ioctl(g_hSysDriver,APUSB_STOP_USB_IMAGE,(unsigned long)&request);
+
+ if ( !Success )
+ {
+ return APN_USB_ERR_STOP_EXP;
+ }
+ }
+
+ return APN_USB_SUCCESS;
+}
+
+
+APN_USB_TYPE OrigApnUsbGetImage( unsigned short *pMem )
+{
+ BOOLEAN Success;
+ ULONG ImageBytesRemaining;
+ ULONG ReceivedSize;
+ ULONG retval;
+ unsigned char *pRequestData;
+ unsigned short RegNumber;
+ struct apIOparam request;
+
+
+ if ( (g_hSysDriver == INVALID_HANDLE_VALUE) || (g_hSysDriver == 0) )
+ {
+ return APN_USB_ERR_OPEN;
+ }
+
+ ImageBytesRemaining = g_UsbImgSizeBytes;
+
+// pRequestData = new UCHAR[IMAGE_BUFFER_SIZE];
+
+ ////////////////////////
+ ULONG LoopCount = g_UsbImgSizeBytes / IMAGE_BUFFER_SIZE;
+ ULONG Remainder = g_UsbImgSizeBytes - ( LoopCount * IMAGE_BUFFER_SIZE );
+ ULONG MemIterator = IMAGE_BUFFER_SIZE / 2;
+ ULONG Counter;
+
+
+ for ( Counter=0; Counter<LoopCount; Counter++ )
+ {
+ request.reg = 0; //check this ***************
+ request.param1= *pMem;
+ request.param2=IMAGE_BUFFER_SIZE;
+ Success=ioctl(g_hSysDriver,APUSB_READ_USB_IMAGE,(unsigned long)&request);
+ ReceivedSize = (unsigned short)retval;
+
+ if ( (!Success) || (ReceivedSize != IMAGE_BUFFER_SIZE) )
+ {
+ Success = 0;
+ break;
+ }
+ else
+ {
+ pMem += MemIterator;
+ }
+ }
+
+ if ( (Success) && (Remainder != 0) )
+ {
+ request.reg = 0; //check this *************************8
+ request.param1= *pMem;
+ request.param2=Remainder;
+ Success=ioctl(g_hSysDriver,APUSB_READ_USB_IMAGE,(unsigned long)&request);
+ ReceivedSize = (unsigned short)retval;
+
+ if ( ReceivedSize != Remainder )
+ Success = 0;
+ }
+
+// delete [] pRequestData;
+
+ if ( !Success )
+ return APN_USB_ERR_IMAGE_DOWNLOAD;
+
+ return APN_USB_SUCCESS; // Success
+}
+
+APN_USB_TYPE ApnUsbGetImage( unsigned short *pMem )
+{
+ BOOLEAN Success;
+ ULONG ImageBytesRemaining;
+ ULONG ReceivedSize;
+ ULONG retval;
+ unsigned char *pRequestData;
+ unsigned short RegNumber;
+ struct apIOparam request;
+
+ Success = 1;
+ if ( (g_hSysDriver == INVALID_HANDLE_VALUE) || (g_hSysDriver == 0) )
+ {
+ return APN_USB_ERR_OPEN;
+ }
+
+ ImageBytesRemaining = g_UsbImgSizeBytes;
+
+
+ ////////////////////////
+ ULONG LoopCount = g_UsbImgSizeBytes / IMAGE_BUFFER_SIZE;
+ ULONG Remainder = g_UsbImgSizeBytes - ( LoopCount * IMAGE_BUFFER_SIZE );
+ ULONG MemIterator = IMAGE_BUFFER_SIZE / 2;
+ ULONG Counter;
+
+
+ for ( Counter=0; Counter<LoopCount; Counter++ )
+ {
+ ReceivedSize = read(g_hSysDriver,pMem,IMAGE_BUFFER_SIZE);
+
+ if ( ReceivedSize != IMAGE_BUFFER_SIZE )
+ {
+ Success = 0;
+ break;
+ }
+ else
+ {
+ pMem += MemIterator;
+ printf(".");
+ }
+ }
+
+ if ( Remainder != 0 )
+ {
+ ReceivedSize = read(g_hSysDriver,pMem,Remainder);
+
+ if ( ReceivedSize != Remainder )
+ Success = 0;
+ }
+ printf("\n");
+
+ if ( !Success )
+ return APN_USB_ERR_IMAGE_DOWNLOAD;
+
+ return APN_USB_SUCCESS; // Success
+}
+
+
+APN_USB_TYPE ApnUsbReset()
+{
+ BOOLEAN Success;
+ ULONG BytesReceived;
+ unsigned short RegNumber;
+ struct apIOparam request;
+
+
+ if ( (g_hSysDriver == INVALID_HANDLE_VALUE) || (g_hSysDriver == 0) )
+ {
+ return APN_USB_ERR_OPEN;
+ }
+
+ request.reg = 0;
+ request.param1 = 0;
+ Success=ioctl(g_hSysDriver,APUSB_USB_RESET,(unsigned long)&request);
+
+ if ( !Success )
+ {
+ return APN_USB_ERR_RESET;
+ }
+
+ return APN_USB_SUCCESS;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/kstars/kstars/indi/apogee/CameraIO_Linux.cpp b/kstars/kstars/indi/apogee/CameraIO_Linux.cpp
new file mode 100644
index 00000000..67d217ec
--- /dev/null
+++ b/kstars/kstars/indi/apogee/CameraIO_Linux.cpp
@@ -0,0 +1,1362 @@
+// CameraIO.cpp: implementation of the CCameraIO class.
+//
+// Copyright (c) 2000 Apogee Instruments Inc.
+//////////////////////////////////////////////////////////////////////
+
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <sched.h>
+#include <unistd.h>
+#include <fcntl.h>
+#define HANDLE int
+#define FALSE 0
+#define DWORD long
+#define _ASSERT assert
+#define REALTIME_PRIORITY_CLASS 1
+#define GetCurrentProcess getpid
+#define LOBYTE(x) ((x) & 0xff)
+#define HIBYTE(x) ((x >> 8) & 0xff)
+
+#define MIRQ1 0x21
+#define MIRQ2 0xA1
+
+#include "time.h"
+//#include "tcl.h"
+//#include "ccd.h"
+#include "CameraIO_Linux.h"
+#include "ApogeeLinux.h"
+
+const int NUM_POSITIONS = 6;
+const int NUM_STEPS_PER_FILTER = 48;
+const int STEP_DELAY = 10;
+
+const unsigned char Steps[] = { 0x10, 0x30, 0x20, 0x60, 0x40, 0xc0, 0x80, 0x90 };
+const int NUM_STEPS = sizeof ( Steps );
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CCameraIO::CCameraIO()
+{
+ InitDefaults();
+
+ m_TDI = false;
+
+ m_Shutter = false;
+ m_FilterPosition = 0;
+ m_FilterStepPos = 0;
+
+ m_WaitingforImage = false;
+ m_WaitingforLine = false;
+
+ m_WaitingforTrigger = false;
+ m_Status = Camera_Status_Idle;
+ m_CoolerStatus = Camera_CoolerStatus_Off;
+
+ m_ExposureBinX = 0;
+ m_ExposureBinY = 0;
+ m_ExposureStartX = 0;
+ m_ExposureStartY = 0;
+ m_ExposureNumX = 0;
+ m_ExposureNumY = 0;
+ m_ExposureColumns = 0;
+ m_ExposureRows = 0;
+ m_ExposureSkipC = 0;
+ m_ExposureSkipR = 0;
+ m_ExposureHFlush = 0;
+ m_ExposureVFlush = 0;
+ m_ExposureBIC = 0;
+ m_ExposureBIR = 0;
+ m_ExposureAIC = 0;
+ m_ExposureRemainingLines = 0;
+ m_ExposureAIR = 0;
+
+ m_RegShadow[ Reg_Command ] = 0;
+ m_RegShadow[ Reg_Timer ] = 0;
+ m_RegShadow[ Reg_VBinning ] = 0;
+ m_RegShadow[ Reg_AICCounter ] = 0;
+ m_RegShadow[ Reg_TempSetPoint ] = 0;
+ m_RegShadow[ Reg_PixelCounter ] = 0;
+ m_RegShadow[ Reg_LineCounter ] = 0;
+ m_RegShadow[ Reg_BICCounter ] = 0;
+
+ m_FastShutterBits_Mode = 0;
+ m_FastShutterBits_Test = 0;
+ m_IRQMask = 0;
+ saveIRQS = 0;
+
+}
+
+CCameraIO::~CCameraIO()
+{
+
+ //::close(fileHandle);
+ close(fileHandle);
+}
+
+////////////////////////////////////////////////////////////
+// System methods
+
+int GetPriorityClass ( HANDLE /*hProcess*/ )
+{
+ int i;
+ i = sched_getscheduler(0);
+ return(i);
+}
+
+int SetPriorityClass ( HANDLE /*hProcess*/, int hPriority)
+{
+ int i;
+ sched_param p;
+
+ if (hPriority) {
+ i = sched_setscheduler(0,SCHED_RR,&p);
+ } else {
+ i = sched_setscheduler(0,SCHED_OTHER,&p);
+ }
+ return(i);
+}
+
+void Sleep (int hTime)
+{
+ timespec t;
+ t.tv_sec= 0;
+ t.tv_nsec = hTime*1000000;
+// nanosleep(&t);
+}
+
+
+
+void ATLTRACE (char * /*msg*/)
+{
+}
+
+
+void CCameraIO::Reset()
+{
+ unsigned short val = 0;
+ Read( Reg_CommandReadback, val ); // Take snapshot of currrent status
+ m_RegShadow[ Reg_Command ] = val; // remember it in our write shadow
+
+ // In case these were left on, turn them off
+ m_RegShadow[ Reg_Command ] &= ~RegBit_FIFOCache; // set bit to 0
+ m_RegShadow[ Reg_Command ] &= ~RegBit_TDIMode; // set bit to 0
+
+ m_RegShadow[ Reg_Command ] |= RegBit_ResetSystem; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_ResetSystem; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_WaitingforImage = false;
+ m_WaitingforLine = false;
+ m_WaitingforTrigger = false;
+}
+
+void CCameraIO::AuxOutput( unsigned char val )
+{
+ // clear bits to 0
+ m_RegShadow[ Reg_TempSetPoint ] &= ~( RegBitMask_PortControl << RegBitShift_PortControl );
+
+ // set our new bits
+ m_RegShadow[ Reg_TempSetPoint ] |= val << RegBitShift_PortControl;
+
+ Write( Reg_TempSetPoint, m_RegShadow[ Reg_TempSetPoint ] );
+}
+
+// Input reg is from 0 to 7, val is any 16 bit number
+void CCameraIO::RegWrite( short reg, unsigned short val )
+{
+ Write( reg, val );
+
+ // Update our shadow register
+ switch ( reg )
+ {
+ case Reg_Command:
+ m_RegShadow[ Reg_Command ] = val;
+ break;
+ case Reg_Timer:
+ m_RegShadow[ Reg_Timer ] = val;
+ break;
+ case Reg_VBinning:
+ m_RegShadow[ Reg_VBinning ] = val;
+ break;
+ case Reg_AICCounter:
+ m_RegShadow[ Reg_AICCounter ] = val;
+ break;
+ case Reg_TempSetPoint:
+ m_RegShadow[ Reg_TempSetPoint ] = val;
+ break;
+ case Reg_PixelCounter:
+ m_RegShadow[ Reg_PixelCounter ] = val;
+ break;
+ case Reg_LineCounter:
+ m_RegShadow[ Reg_LineCounter ] = val;
+ break;
+ case Reg_BICCounter:
+ m_RegShadow[ Reg_BICCounter ] = val;
+ break;
+ default:
+ _ASSERT( FALSE ); // application program bug
+ }
+}
+
+// Input reg is from 8 to 12, returned val is any 16 bit number
+void CCameraIO::RegRead( short reg, unsigned short& val )
+{
+ Read( reg, val );
+}
+
+bool CCameraIO::FilterHome()
+{
+ HANDLE hProcess(0);
+ DWORD Class(0);
+
+ if ( m_HighPriority )
+ { // Store current process class and priority
+ hProcess = GetCurrentProcess();
+ Class = GetPriorityClass ( hProcess );
+ SetPriorityClass ( hProcess, REALTIME_PRIORITY_CLASS );
+ }
+
+ // Find the home position
+ m_FilterPosition = 0;
+ int Safety = 0;
+ for (int I = 0; I < NUM_POSITIONS * NUM_STEPS_PER_FILTER * 2; I++)
+ {
+ // Advance the filter one step
+ m_FilterStepPos += 1;
+ if (m_FilterStepPos >= NUM_STEPS) m_FilterStepPos = 0;
+ unsigned char Step = Steps[ m_FilterStepPos ];
+
+ AuxOutput( Step );
+ Sleep ( STEP_DELAY );
+
+ // Check for strobe
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( val & RegBit_GotTrigger )
+ {
+ // Cycle all the way around if it's on the first time
+ if (I < NUM_STEPS_PER_FILTER)
+ {
+ if (++Safety > NUM_STEPS_PER_FILTER * 2)
+ {
+ // Restore normal priority
+ if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
+ return false;
+ }
+ I = 0;
+ continue;
+ }
+
+ // Continue cycling until we get clear of the opto mirror
+ for (int J = 0; J < NUM_STEPS_PER_FILTER; J++)
+ {
+ // Advance the filter one step
+ m_FilterStepPos += 1;
+ if (m_FilterStepPos >= NUM_STEPS) m_FilterStepPos = 0;
+ unsigned char Step = Steps[ m_FilterStepPos ];
+
+ AuxOutput( Step );
+ Sleep ( STEP_DELAY );
+
+ val = 0;
+ Read( Reg_Status, val );
+ if ( val & RegBit_GotTrigger )
+ {
+ Sleep ( 10 );
+
+ val = 0;
+ Read( Reg_Status, val );
+ if ( val & RegBit_GotTrigger )
+ {
+ // Restore normal priority
+ if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
+ return true;
+ }
+ }
+ }
+
+ // Restore normal priority
+ if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
+ return true;
+ }
+ }
+
+ // Restore normal priority
+ if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
+ return false;
+}
+
+void CCameraIO::FilterSet( short Slot )
+{
+ // Determine how far we have to move
+ int Pos = Slot - m_FilterPosition;
+ if (Pos < 0) Pos += NUM_POSITIONS;
+
+ HANDLE hProcess(0);
+ DWORD Class(0);
+
+ if ( m_HighPriority )
+ { // Store current process class and priority
+ hProcess = GetCurrentProcess();
+ Class = GetPriorityClass ( hProcess );
+ SetPriorityClass ( hProcess, REALTIME_PRIORITY_CLASS );
+ }
+
+ for (int I = 0; I < Pos; I++)
+ {
+ // Advance one position
+ for (int J = 0; J < NUM_STEPS_PER_FILTER; J++)
+ {
+ m_FilterStepPos += 1;
+ if (m_FilterStepPos >= NUM_STEPS) m_FilterStepPos = 0;
+ unsigned char Step = Steps[ m_FilterStepPos ];
+
+ AuxOutput( Step );
+ Sleep ( STEP_DELAY );
+ }
+ }
+
+ if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
+
+ m_FilterPosition = Slot;
+}
+
+////////////////////////////////////////////////////////////
+// Normal exposure methods
+
+bool CCameraIO::Expose( double Duration, bool Light )
+{
+ if ( !m_TDI && ( Duration < m_MinExposure || Duration > m_MaxExposure ) ) return false;
+
+ // Validate all input variables
+ if ( m_Columns < 1 || m_Columns > MAXCOLUMNS ) return false;
+ m_ExposureColumns = m_Columns;
+
+ if ( m_Rows < 1 || m_Rows > MAXROWS ) return false;
+ m_ExposureRows = m_Rows;
+
+ if ( m_SkipC < 0 ) return false;
+ m_ExposureSkipC = m_SkipC;
+
+ if ( m_SkipR < 0 ) return false;
+ m_ExposureSkipR = m_SkipR;
+
+ if ( m_HFlush < 1 || m_HFlush > MAXHBIN ) return false;
+ m_ExposureHFlush = m_HFlush;
+
+ if ( m_VFlush < 1 || m_VFlush > MAXVBIN ) return false;
+ m_ExposureVFlush = m_VFlush;
+
+ if ( m_BIC < 1 || m_BIC > MAXCOLUMNS ) return false;
+ m_ExposureBIC = m_BIC;
+
+ if ( m_BIR < 1 || m_BIR > MAXROWS ) return false;
+ m_ExposureBIR = m_BIR;
+
+ // Validate all input variables
+ if ( m_BinX < 1 || m_BinX > MAXHBIN ) return false;
+ m_ExposureBinX = m_BinX;
+
+ if ( m_StartX < 0 || m_StartX >= MAXCOLUMNS ) return false;
+ m_ExposureStartX = m_StartX;
+
+ if ( m_NumX < 1 || m_NumX * m_BinX > m_ImgColumns ) return false;
+ m_ExposureNumX = m_NumX;
+
+ // Calculate BIC, RawPixelCount, AIC
+ unsigned short BIC = m_ExposureBIC + m_ExposureStartX; // unbinned columns
+ unsigned short RawPixelCount = m_ExposureNumX * m_ExposureBinX;
+ m_ExposureAIC = m_ExposureColumns - BIC - RawPixelCount; // unbinned columns
+
+ if ( m_BinY < 1 || m_BinY > MAXVBIN ) return false;
+ m_ExposureBinY = m_BinY;
+
+ unsigned short VBin(0), row_offset(0);
+
+ if ( m_TDI )
+ { // row_offset is the drift time in milliseconds when in TDI mode
+ row_offset = (unsigned short) (Duration * 1000 + 0.5);
+ Duration = 0.0;
+ }
+ else
+ {
+ if ( m_StartY < 0 || m_StartX >= MAXROWS ) return false;
+ m_ExposureStartY = m_StartY;
+
+ if ( m_NumY < 1 || m_NumY * m_BinY > m_ImgRows ) return false;
+ m_ExposureNumY = m_NumY;
+
+ unsigned short BIR = m_ExposureBIR + m_ExposureStartY; // unbinned rows
+ if ( BIR >= MAXROWS ) return false;
+ m_ExposureAIR = m_ExposureRows - BIR - m_ExposureNumY * m_ExposureBinY; // unbinned rows
+
+ if ( m_VFlush > BIR )
+ {
+ VBin = BIR;
+ m_ExposureRemainingLines = 0;
+ }
+ else
+ {
+ VBin = m_VFlush;
+ m_ExposureRemainingLines = BIR % VBin; // unbinned rows
+ }
+ row_offset = BIR - m_ExposureRemainingLines; // unbinned rows
+ }
+
+ StopFlushing();
+ Reset();
+
+ LoadColumnLayout( m_ExposureAIC, BIC, (unsigned short) m_ExposureNumX + m_ExposureSkipC );
+ LoadTimerAndBinning( Duration, (unsigned short) m_ExposureHFlush, VBin );
+ LoadLineCounter( row_offset );
+
+ if ( m_TDI )
+ {
+ // Turn on TDI
+ m_RegShadow[ Reg_Command ] |= RegBit_TDIMode; // set bit to 1
+
+ // Disable FIFO cache
+ m_RegShadow[ Reg_Command ] &= ~RegBit_FIFOCache; // set bit to 0
+
+ // Set shutter override
+ if ( Light )
+ m_RegShadow[ Reg_Command ] |= RegBit_ShutterOverride; // set bit to 1
+ else
+ m_RegShadow[ Reg_Command ] &= ~RegBit_ShutterOverride; // set bit to 0
+
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ // Update our status
+ m_Shutter = Light;
+ m_WaitingforTrigger = false;
+ m_WaitingforLine = false;
+ }
+ else
+ {
+ // Set shutter
+ if ( Light )
+ m_RegShadow[ Reg_Command ] |= RegBit_ShutterEnable; // set bit to 1
+ else
+ m_RegShadow[ Reg_Command ] &= ~RegBit_ShutterEnable; // set bit to 0
+
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ // Update our status
+ unsigned short val = 0;
+ Read( Reg_CommandReadback, val );
+ if ( val & RegBit_ShutterOverride )
+ m_Shutter = true;
+ else
+ m_Shutter = Light;
+
+ if ( ( val & RegBit_TriggerEnable ) )
+ m_WaitingforTrigger = true;
+ else
+ m_WaitingforTrigger = false;
+
+ // Start the exposure
+ m_RegShadow[ Reg_Command ] |= RegBit_StartTimer; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_StartTimer; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_WaitingforImage = true;
+ }
+
+ return true;
+}
+
+/*bool CCameraIO::BufferImage(char *bufferName )
+{
+ unsigned short *pImageData;
+ bool status;
+ short cols,rows,hbin,vbin;
+ short xSize, ySize;
+
+ cols = m_NumX*m_BinX;
+ rows = m_NumY*m_BinY;
+ hbin = m_BinX;
+ vbin = m_BinY;
+
+ pImageData = (unsigned short *)CCD_locate_buffer(bufferName, 2 , cols, rows, hbin, vbin );
+ if (pImageData == NULL) {
+ return 0;
+ }
+
+ status = GetImage(pImageData, xSize, ySize);
+ return status;
+}*/
+
+bool CCameraIO::GetImage( unsigned short* pImageData, short& xSize, short& ySize )
+{
+ int i;
+ unsigned short BIC = m_ExposureBIC + m_ExposureStartX;
+
+ // Update internal variables in case application did not poll read_Status
+ m_WaitingforTrigger = false;
+ m_WaitingforLine = false;
+
+ if ( m_WaitingforImage )
+ { // In case application did not poll read_Status
+ m_WaitingforImage = false;
+
+ /////////////////////////////////////
+ // Wait until camera is done flushing
+ clock_t StopTime = clock() + long( m_Timeout * CLOCKS_PER_SEC ); // wait at most m_Timeout seconds
+ while ( true )
+ {
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( ( val & RegBit_FrameDone ) != 0 ) break;
+
+ if ( clock() > StopTime ) return false; // Timed out
+ }
+ }
+
+// MaskIrqs();
+
+ /////////////////////////////////////
+ // Update our internal status
+ unsigned short val = 0;
+ Read( Reg_CommandReadback, val );
+ if ( !( val & RegBit_ShutterOverride ) ) m_Shutter = false;
+
+ StopFlushing();
+ LoadColumnLayout( m_ExposureAIC, BIC, (unsigned short) m_ExposureNumX + m_ExposureSkipC );
+
+ if ( m_ExposureRemainingLines > 0 )
+ {
+ LoadTimerAndBinning( 0.0, m_ExposureHFlush, m_ExposureRemainingLines );
+
+ /////////////////////////////////////
+ // Clock out the remaining lines
+ m_RegShadow[ Reg_Command ] |= RegBit_StartNextLine; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_StartNextLine; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+
+ /////////////////////////////////////
+ // Wait until camera is done clocking
+ clock_t StopTime = clock() + CLOCKS_PER_SEC; // wait at most one second
+ while ( true )
+ {
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( ( val & RegBit_LineDone ) != 0 ) break; // Line done
+
+ if ( clock() > StopTime )
+ {
+ Flush();
+ return false; // Timed out, no image available
+ }
+ }
+ }
+
+ LoadTimerAndBinning( 0.0, m_ExposureBinX, m_ExposureBinY );
+
+ bool ret = false; // assume failure
+
+ // NB Application must have allocated enough memory or else !!!
+ if ( pImageData != NULL )
+ {
+ HANDLE hProcess(0);
+ DWORD Class(0);
+
+ if ( m_HighPriority )
+ { // Store current process class and priority
+ hProcess = GetCurrentProcess();
+ Class = GetPriorityClass ( hProcess );
+ SetPriorityClass ( hProcess, REALTIME_PRIORITY_CLASS );
+ }
+
+ m_RegShadow[ Reg_Command ] |= RegBit_FIFOCache; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ long XPixels = long( m_ExposureNumX );
+ long SkipPixels = long( m_ExposureSkipC );
+ for (i = 0; i < m_ExposureSkipR; i++)
+ {
+ if ( ReadLine( SkipPixels, XPixels, pImageData ) ) break;
+ }
+
+ if ( i == m_ExposureSkipR )
+ { // We have skipped all the lines
+ long YPixels = long( m_ExposureNumY );
+ unsigned short* pLineBuffer = pImageData;
+ for (i = 0; i < YPixels; i++)
+ {
+ if ( ReadLine( SkipPixels, XPixels, pLineBuffer ) ) break;
+ pLineBuffer += XPixels;
+ }
+
+ if ( i == YPixels ) ret = true; // We have read all the lines
+ }
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_FIFOCache; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ //Restore priority
+ if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
+ }
+
+// UnmaskIrqs();
+
+ if ( ret )
+ { // We were successfull
+ Flush( m_ExposureAIR ); // flush after imaging rows
+
+ xSize = m_ExposureNumX;
+ ySize = m_ExposureNumY;
+
+ if ( m_DataBits == 16 )
+ { // Take care of two's complement converters
+ unsigned short *Ptr = pImageData;
+ short *Ptr2 = (short *) pImageData;
+ long Size = m_ExposureNumX * m_ExposureNumY;
+ for (i = 0; i < Size; i++)
+ {
+ *Ptr++ = (unsigned short) *Ptr2++ + 32768 ;
+ }
+ }
+
+ }
+ else
+ { // Something went wrong
+ xSize = 0;
+ ySize = 0;
+ }
+
+ Flush(); // start normal flushing
+
+ return ret;
+}
+
+////////////////////////////////////////////////////////////
+// Drift scan methods
+
+bool CCameraIO::DigitizeLine()
+{
+ /////////////////////////////////////
+ // All of these are done just in case
+ // since they are called in Expose()
+ StopFlushing();
+
+ unsigned short BIC = m_ExposureBIC + m_ExposureStartX;
+ LoadColumnLayout( m_ExposureAIC, BIC, (unsigned short) m_ExposureNumX + m_ExposureSkipC );
+ LoadTimerAndBinning( 0.0, m_ExposureBinX, m_ExposureBinY );
+
+ // Disable FIFO cache
+ m_RegShadow[ Reg_Command ] &= ~RegBit_FIFOCache; // set bit to 0
+ /////////////////////////////////////
+
+ /////////////////////////////////////
+ // Clock out the line
+ m_RegShadow[ Reg_Command ] |= RegBit_StartNextLine; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_StartNextLine; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+
+ m_WaitingforLine = true;
+ return true;
+}
+
+bool CCameraIO::GetLine( unsigned short* pLineData, short& xSize )
+{
+ int i;
+
+ if ( m_WaitingforLine )
+ { // In case application did not poll read_Status
+ m_WaitingforLine = false;
+
+ /////////////////////////////////////
+ // Wait until camera is done clocking
+ clock_t StopTime = clock() + CLOCKS_PER_SEC; // wait at most one second
+ while ( true )
+ {
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( ( val & RegBit_LineDone ) != 0 ) break; // Line done
+
+ if ( clock() > StopTime )
+ {
+ Flush();
+ return false; // Timed out, no line available
+ }
+ }
+ }
+
+ bool ret = false; // assume failure
+
+// MaskIrqs();
+
+ // NB Application must have allocated enough memory or else !!!
+ if ( pLineData != NULL )
+ {
+ HANDLE hProcess(0);
+ DWORD Class(0);
+
+ if ( m_HighPriority )
+ { // Store current process class and priority
+ hProcess = GetCurrentProcess();
+ Class = GetPriorityClass ( hProcess );
+ SetPriorityClass ( hProcess, REALTIME_PRIORITY_CLASS );
+ }
+
+ long XPixels = long( m_ExposureNumX );
+ long SkipPixels = long( m_ExposureSkipC );
+
+ if ( ReadLine( SkipPixels, XPixels, pLineData ) )
+ { // Something went wrong
+ xSize = 0;
+ ret = false;
+ }
+ else
+ {
+ xSize = m_ExposureNumX;
+
+ if ( m_DataBits == 16 )
+ { // Take care of two's complement converters
+ unsigned short *Ptr = pLineData;
+ short *Ptr2 = (short *) pLineData;
+ long Size = m_ExposureNumX;
+ for (i = 0; i < Size; i++)
+ {
+ *Ptr++ = (unsigned short) *Ptr2++ + 32768 ;
+ }
+ }
+
+ ret = true;
+ }
+
+ //Restore priority
+ if ( m_HighPriority ) SetPriorityClass ( hProcess, Class );
+ }
+
+// UnmaskIrqs();
+ return ret;
+}
+
+////////////////////////////////////////////////////////////
+// Easy to use methods
+
+bool CCameraIO::Snap( double Duration, bool Light, unsigned short* pImageData, short& xSize, short& ySize )
+{
+ // NB This also demonstrates how an application might use the
+ // Expose and GetImage routines.
+
+ bool ret = Expose( Duration, Light );
+ if ( !ret ) return false;
+
+ if ( m_WaitingforTrigger )
+ {
+ Camera_Status stat;
+ while ( true )
+ { // This will wait forever if no trigger happens
+ stat = read_Status();
+ if ( stat == Camera_Status_Exposing ) break;
+ Sleep( 220 ); // dont bog down the CPU while polling
+ }
+ m_WaitingforTrigger = false;
+ }
+
+ // Only wait a time slightly greater than the duration of the exposure
+ // but enough for the BIR to flush out
+ clock_t StopTime = clock() + long( ( 1.2 * Duration + m_Timeout ) * CLOCKS_PER_SEC );
+ while ( true )
+ {
+ Camera_Status stat = read_Status();
+ if ( stat == Camera_Status_ImageReady ) break;
+
+ if ( clock() > StopTime ) return false; // Timed out, no image available
+ Sleep( 220 ); // dont bog down the CPU while polling
+ }
+
+ return GetImage( pImageData, xSize, ySize );
+}
+
+////////////////////////////////////////////////////////////
+// Camera Settings
+
+Camera_Status CCameraIO::read_Status()
+{
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+
+ if ( val & RegBit_Exposing ) //11.0
+ {
+ ATLTRACE( "Exposing\r\n" );
+ m_WaitingforTrigger = false;
+ m_Status = Camera_Status_Exposing;
+ }
+
+ else if ( m_WaitingforTrigger )
+ m_Status = Camera_Status_Waiting;
+
+ else if ( m_WaitingforImage && ( val & RegBit_FrameDone ) ) //11.11
+ {
+ ATLTRACE( "ImageReady\r\n" );
+ m_WaitingforImage = false;
+ m_Status = Camera_Status_ImageReady;
+ }
+
+ else if ( m_WaitingforLine && ( val & RegBit_LineDone ) ) //11.1
+ {
+ ATLTRACE( "LineReady\r\n" );
+ m_WaitingforLine = false;
+ m_Status = Camera_Status_LineReady;
+ }
+ else if ( m_WaitingforImage || m_WaitingforLine )
+ {
+ ATLTRACE( "Flushing\r\n" );
+ m_Status = Camera_Status_Flushing;
+ }
+ else
+ m_Status = Camera_Status_Idle;
+
+ return m_Status;
+}
+
+bool CCameraIO::read_Present()
+{
+// This does not work on all cameras
+/*
+ m_RegShadow[ Reg_BICCounter ] |= RegBit_LoopbackTest; // set bit to 1
+ Write( Reg_BICCounter, m_RegShadow[ Reg_BICCounter ] );
+
+ bool FailedLoopback = false;
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( !( val & RegBit_LoopbackTest ) ) FailedLoopback = true;
+
+ m_RegShadow[ Reg_BICCounter ] &= ~RegBit_LoopbackTest; // clear bit to 0
+ Write( Reg_BICCounter, m_RegShadow[ Reg_BICCounter ] );
+
+ Read( Reg_Status, val );
+ if ( val & RegBit_LoopbackTest ) FailedLoopback = true;
+*/
+
+ unsigned short val = 0;
+ Read( Reg_CommandReadback, val ); // Take snapshot of currrent status
+ m_RegShadow[ Reg_Command ] = val; // remember it in our write shadow
+
+ bool TriggerEnabled = ( val & RegBit_TriggerEnable ) != 0;
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_TriggerEnable;// clear bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ Read( Reg_CommandReadback, val ); // get currrent status
+ if ( val & RegBit_TriggerEnable ) return false;
+
+ m_RegShadow[ Reg_Command ] |= RegBit_TriggerEnable; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ Read( Reg_CommandReadback, val ); // get currrent status
+ if ( !(val & RegBit_TriggerEnable) ) return false;
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_TriggerEnable;// clear bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ Read( Reg_CommandReadback, val ); // get currrent status
+ if ( val & RegBit_TriggerEnable ) return false;
+
+ if ( TriggerEnabled )
+ { // Set it back the way it was
+ m_RegShadow[ Reg_Command ] |= RegBit_TriggerEnable; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ }
+ return true;
+}
+
+bool CCameraIO::read_Shutter()
+{
+ unsigned short regval = 0;
+ Read( Reg_Status, regval );
+ if ( !( regval & RegBit_Exposing ) )
+ { // We are not exposing, but might have finnshed an exposure
+ // and have not called GetImage yet, so update our internal variable
+ regval = 0;
+ Read( Reg_CommandReadback, regval );
+ if ( !( regval & RegBit_ShutterOverride ) )
+ // The shutter override is not on, so the shutter must be closed
+ m_Shutter = false;
+ }
+
+ return m_Shutter;
+}
+
+bool CCameraIO::read_ForceShutterOpen()
+{
+ unsigned short val = 0;
+ Read( Reg_CommandReadback, val );
+ return ( ( val & RegBit_ShutterOverride ) != 0 );
+}
+
+void CCameraIO::write_ForceShutterOpen( bool val )
+{
+ if ( val )
+ {
+ m_RegShadow[ Reg_Command ] |= RegBit_ShutterOverride; // set bit to 1
+ m_Shutter = true; // shutter will open immediately now matter what is going on
+ }
+ else
+ {
+ m_RegShadow[ Reg_Command ] &= ~RegBit_ShutterOverride; // clear bit to 0
+
+ unsigned short regval = 0;
+ Read( Reg_Status, regval );
+ if ( ( regval & RegBit_Exposing ) )
+ {
+ // Shutter will remain open if a Light frame is being taken
+ // however if a dark frame was being exposed while the
+ // override was on or the override is turned on during the exposure
+ // and now is turned off (dumb idea but some app might do it!)
+ // we must update our variable since the shutter will close
+ // when override gets turned off below
+ regval = 0;
+ Read( Reg_CommandReadback, regval );
+ if ( !( regval & RegBit_ShutterEnable ) ) m_Shutter = false;
+ }
+ else
+ { // Not currently exposing so shutter will close
+ // once override is turned off, update our variable
+ m_Shutter = false;
+ }
+ }
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+}
+
+
+
+bool CCameraIO::read_LongCable()
+{
+ unsigned short val = 0;
+ Read( Reg_CommandReadback, val );
+ return ( ( val & RegBit_CableLength ) != 0 );
+}
+
+void CCameraIO::write_Shutter( bool val )
+{
+ if ( val )
+ m_RegShadow[ Reg_Command ] |= RegBit_ShutterEnable; // set bit to 1
+ else
+ m_RegShadow[ Reg_Command ] &= ~RegBit_ShutterEnable; // clear bit to 0
+
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+}
+
+void CCameraIO::write_LongCable( bool val )
+{
+ if ( val )
+ m_RegShadow[ Reg_Command ] |= RegBit_CableLength; // set bit to 1
+ else
+ m_RegShadow[ Reg_Command ] &= ~RegBit_CableLength; // clear bit to 0
+
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+}
+
+
+short CCameraIO::read_Mode()
+{
+ return ( ( m_RegShadow[ Reg_LineCounter ] >> RegBitShift_Mode ) & RegBitMask_Mode );
+}
+
+void CCameraIO::write_Mode( short val )
+{
+ // clear bits to 0
+ m_RegShadow[ Reg_LineCounter ] &= ~( RegBitMask_Mode << RegBitShift_Mode );
+
+ // set our new bits
+ m_RegShadow[ Reg_LineCounter ] |= ( (unsigned short) val & RegBitMask_Mode ) << RegBitShift_Mode;
+
+ Write( Reg_LineCounter, m_RegShadow[ Reg_LineCounter ] );
+}
+
+short CCameraIO::read_TestBits()
+{
+ return ( ( m_RegShadow[ Reg_BICCounter ] >> RegBitShift_Test ) & RegBitMask_Test );
+}
+
+void CCameraIO::write_TestBits( short val )
+{
+ // clear bits to 0
+ m_RegShadow[ Reg_BICCounter ] &= ~( RegBitMask_Test << RegBitShift_Test );
+
+ // set our new bits
+ m_RegShadow[ Reg_BICCounter ] |= ( (unsigned short) val & RegBitMask_Test ) << RegBitShift_Test;
+
+ Write( Reg_BICCounter, m_RegShadow[ Reg_BICCounter ] );
+}
+
+
+short CCameraIO::read_Test2Bits()
+{
+ return ( ( m_RegShadow[ Reg_AICCounter ] >> RegBitShift_Test2 ) & RegBitMask_Test2 );
+}
+
+void CCameraIO::write_Test2Bits( short val )
+{
+ // clear bits to 0
+ m_RegShadow[ Reg_AICCounter ] &= ~( RegBitMask_Test2 << RegBitShift_Test2 );
+
+ // set our new bits
+ m_RegShadow[ Reg_AICCounter ] |= ( (unsigned short) val & RegBitMask_Test2 ) << RegBitShift_Test2;
+
+ Write( Reg_AICCounter, m_RegShadow[ Reg_AICCounter ] );
+}
+
+bool CCameraIO::read_FastReadout()
+{
+ unsigned short val = 0;
+ Read( Reg_CommandReadback , val );
+ return ( ( val & RegBit_Focus ) != 0 );
+}
+
+void CCameraIO::write_FastReadout( bool val )
+{
+ if ( val )
+ m_RegShadow[ Reg_Command ] |= RegBit_Focus; // set bit to 1
+ else
+ m_RegShadow[ Reg_Command ] &= ~RegBit_Focus; // clear bit to 0
+
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+}
+
+bool CCameraIO::read_UseTrigger()
+{
+ unsigned short val = 0;
+ Read( Reg_CommandReadback , val );
+ return ( ( val & RegBit_TriggerEnable ) != 0 );
+}
+
+void CCameraIO::write_UseTrigger( bool val )
+{
+ if ( val )
+ m_RegShadow[ Reg_Command ] |= RegBit_TriggerEnable; // set bit to 1
+ else
+ m_RegShadow[ Reg_Command ] &= ~RegBit_TriggerEnable; // clear bit to 0
+
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+}
+
+////////////////////////////////////////////////////////////
+// Cooler Settings
+
+double CCameraIO::read_CoolerSetPoint()
+{
+ // Get the setting from the shadow registers
+ short DACunits = short( ( m_RegShadow[ Reg_TempSetPoint ] >> RegBitShift_TempSetPoint ) & RegBitMask_TempSetPoint );
+ return ( DACunits - m_TempCalibration ) / m_TempScale;
+}
+
+void CCameraIO::write_CoolerSetPoint( double val )
+{
+ // clear bits to 0
+ m_RegShadow[ Reg_TempSetPoint ] &= ~( RegBitMask_TempSetPoint << RegBitShift_TempSetPoint );
+
+ // Calculate DAC units from degrees Celcius
+ unsigned short DACunits = (unsigned )( m_TempScale * val ) + m_TempCalibration ;
+
+ // set our new bits
+ m_RegShadow[ Reg_TempSetPoint ] |= ( DACunits & RegBitMask_TempSetPoint ) << RegBitShift_TempSetPoint;
+
+ Write( Reg_TempSetPoint, m_RegShadow[ Reg_TempSetPoint ] );
+}
+
+Camera_CoolerStatus CCameraIO::read_CoolerStatus()
+{
+ unsigned short val = 0;
+ Read( Reg_CommandReadback, val );
+
+ if ( val & RegBit_CoolerEnable ) //12.15
+ {
+ unsigned short val2 = 0;
+ Read( Reg_Status, val2 );
+
+ if ( val & RegBit_CoolerShutdown ) //12.8
+ {
+ if ( val2 & RegBit_ShutdownComplete ) //11.6
+ m_CoolerStatus = Camera_CoolerStatus_AtAmbient;
+ else
+ m_CoolerStatus = Camera_CoolerStatus_RampingToAmbient;
+ }
+ else
+ {
+ if ( val2 & RegBit_TempAtMax ) //11.5
+ m_CoolerStatus = Camera_CoolerStatus_AtMax;
+ else if ( val2 & RegBit_TempAtMin ) //11.4
+ m_CoolerStatus = Camera_CoolerStatus_AtMin;
+ else if ( val2 & RegBit_TempAtSetPoint ) //11.7
+ m_CoolerStatus = Camera_CoolerStatus_AtSetPoint;
+ // Check against last known cooler status
+ else if ( m_CoolerStatus == Camera_CoolerStatus_AtSetPoint )
+ m_CoolerStatus = Camera_CoolerStatus_Correcting;
+ else
+ m_CoolerStatus = Camera_CoolerStatus_RampingToSetPoint;
+ }
+ }
+ else
+ m_CoolerStatus = Camera_CoolerStatus_Off;
+
+ return m_CoolerStatus;
+}
+
+Camera_CoolerMode CCameraIO::read_CoolerMode()
+{
+ unsigned short val = 0;
+ Read( Reg_CommandReadback, val );
+
+ if ( val & RegBit_CoolerShutdown )
+ return Camera_CoolerMode_Shutdown;
+ else if ( val & RegBit_CoolerEnable )
+ return Camera_CoolerMode_On;
+ else
+ return Camera_CoolerMode_Off;
+}
+
+void CCameraIO::write_CoolerMode( Camera_CoolerMode val )
+{
+ switch ( val )
+ {
+ case Camera_CoolerMode_Off:
+ m_RegShadow[ Reg_Command ] &= ~( RegBit_CoolerEnable ); // clear bit to 0
+ m_RegShadow[ Reg_Command ] &= ~( RegBit_CoolerShutdown ); // clear bit to 0
+ break;
+ case Camera_CoolerMode_On:
+ m_RegShadow[ Reg_Command ] |= RegBit_CoolerEnable; // set bit to 1
+ break;
+ case Camera_CoolerMode_Shutdown:
+ m_RegShadow[ Reg_Command ] |= RegBit_CoolerShutdown; // set bit to 1
+ break;
+ default:
+ return;
+ }
+
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+}
+
+double CCameraIO::read_Temperature()
+{
+ if ( m_TempScale == 0.0 )
+ return 0.0;
+ else
+ {
+ unsigned short val = 0;
+ Read( Reg_TempData, val );
+
+ short DACunits = short( ( val >> RegBitShift_TempData ) & RegBitMask_TempData );
+
+ return ( DACunits - m_TempCalibration ) / m_TempScale;
+ }
+}
+
+// Load line counter
+void CCameraIO::LoadLineCounter( unsigned short rows )
+{
+ /////////////////////////////////////
+ // Write out Line_Count - in unbinned rows
+ // clear bits to 0
+ m_RegShadow[ Reg_LineCounter ] &= ~( RegBitMask_LineCounter << RegBitShift_LineCounter );
+ // set our new bits
+ m_RegShadow[ Reg_LineCounter ] |= ( rows & RegBitMask_LineCounter ) << RegBitShift_LineCounter;
+
+ Write( Reg_LineCounter, m_RegShadow[ Reg_LineCounter ] );
+ /////////////////////////////////////
+}
+
+// Load AIC, BIC and pixel count into registers
+void CCameraIO::LoadColumnLayout( unsigned short aic, unsigned short bic, unsigned short pixels )
+{
+ /////////////////////////////////////
+ // Write out AIC - in unbinned columns
+ // clear bits to 0
+ m_RegShadow[ Reg_AICCounter ] &= ~( RegBitMask_AICCounter << RegBitShift_AICCounter );
+ // set our new bits
+ m_RegShadow[ Reg_AICCounter ] |= ( aic & RegBitMask_AICCounter ) << RegBitShift_AICCounter;
+
+ Write( Reg_AICCounter, m_RegShadow[ Reg_AICCounter ] );
+ /////////////////////////////////////
+
+ /////////////////////////////////////
+ // Write out BIC - in unbinned columns
+ // clear bits to 0
+ m_RegShadow[ Reg_BICCounter ] &= ~( RegBitMask_BICCounter << RegBitShift_BICCounter );
+ // set our new bits
+ m_RegShadow[ Reg_BICCounter ] |= ( bic & RegBitMask_BICCounter ) << RegBitShift_BICCounter;
+
+ Write( Reg_BICCounter, m_RegShadow[ Reg_BICCounter ] );
+ /////////////////////////////////////
+
+ /////////////////////////////////////
+ // Write out pixel count - in binned columns
+ // clear bits to 0
+ m_RegShadow[ Reg_PixelCounter ] &= ~( RegBitMask_PixelCounter << RegBitShift_PixelCounter );
+ // set our new bits
+ m_RegShadow[ Reg_PixelCounter ] |= ( pixels & RegBitMask_PixelCounter ) << RegBitShift_PixelCounter;
+
+ Write( Reg_PixelCounter, m_RegShadow[ Reg_PixelCounter ] );
+ /////////////////////////////////////
+}
+
+// Load timer, vertical binning and horizontal binning in to registers
+// If Duration parameter is 0 the current timer value will be retained.
+// The VBin and HBin parameters are one based, the HBin value
+// is converted to zero base inside this routine.
+void CCameraIO::LoadTimerAndBinning( double Duration, unsigned short HBin, unsigned short VBin )
+{
+ /////////////////////////////////////
+ // Write out HBin for flushing
+ // clear bits to 0
+ m_RegShadow[ Reg_PixelCounter ] &= ~( RegBitMask_HBinning << RegBitShift_HBinning );
+ // set our new bits
+ m_RegShadow[ Reg_PixelCounter ] |= ( ( HBin - 1 ) & RegBitMask_HBinning ) << RegBitShift_HBinning;
+
+ Write( Reg_PixelCounter, m_RegShadow[ Reg_PixelCounter ] );
+ /////////////////////////////////////
+
+ /////////////////////////////////////
+ // Write out VBin for flushing and Timer
+ if ( Duration > 0.0 )
+ {
+ if ( Duration > m_MaxExposure ) Duration = m_MaxExposure;
+
+ long valTimer;
+ if ( m_FastShutter && Duration <= 1048.575 )
+ { // Automatically switch to high precision mode
+ valTimer = long( ( Duration * 1000 ) + 0.5 );
+ m_RegShadow[ Reg_LineCounter ] |= ( m_FastShutterBits_Mode & RegBitMask_Mode ) << RegBitShift_Mode;
+ m_RegShadow[ Reg_BICCounter ] |= ( m_FastShutterBits_Test & RegBitMask_Test ) << RegBitShift_Test;
+ }
+ else
+ {
+ valTimer = long( ( Duration * 100 ) + 0.5 );
+ if ( m_FastShutter )
+ { // Disable high precision mode
+ m_RegShadow[ Reg_LineCounter ] &= ~( m_FastShutterBits_Mode & RegBitMask_Mode ) << RegBitShift_Mode;
+ m_RegShadow[ Reg_BICCounter ] &= ~( m_FastShutterBits_Test & RegBitMask_Test ) << RegBitShift_Test;
+ }
+ }
+
+ if ( m_FastShutter )
+ {
+ Write( Reg_LineCounter, m_RegShadow[ Reg_LineCounter ] );
+ Write( Reg_BICCounter, m_RegShadow[ Reg_BICCounter ] );
+ }
+
+ if ( valTimer <= 0 ) valTimer = 1; // Safety since firmware doesnt like zero
+
+ unsigned short valTimerLow = (unsigned short) (valTimer & 0x0000FFFF);
+ unsigned short valTimerHigh = (unsigned short) (valTimer >> 16);
+
+ // Enable loading of timer values
+ m_RegShadow[ Reg_Command ] |= RegBit_TimerLoad; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ // clear bits to 0
+ m_RegShadow[ Reg_Timer ] = 0;
+ // set our new bits
+ m_RegShadow[ Reg_Timer ] |= ( valTimerLow & RegBitMask_Timer )<< RegBitShift_Timer;
+ Write( Reg_Timer, m_RegShadow[ Reg_Timer ] );
+
+ // clear bits to 0
+ m_RegShadow[ Reg_VBinning ] = 0;
+
+ // set our new bits
+ m_RegShadow[ Reg_VBinning ] |= ( VBin & RegBitMask_VBinning ) << RegBitShift_VBinning;
+ m_RegShadow[ Reg_VBinning ] |= ( valTimerHigh & RegBitMask_Timer2 ) << RegBitShift_Timer2;
+ Write( Reg_VBinning, m_RegShadow[ Reg_VBinning ] );
+
+ // Disable loading of timer values
+ m_RegShadow[ Reg_Command ] &= ~RegBit_TimerLoad; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+ }
+ else
+ {
+ // clear bits to 0
+ m_RegShadow[ Reg_VBinning ] &= ~( RegBitMask_VBinning << RegBitShift_VBinning );
+
+ // set our new bits
+ m_RegShadow[ Reg_VBinning ] |= ( VBin & RegBitMask_VBinning ) << RegBitShift_VBinning;
+ Write( Reg_VBinning, m_RegShadow[ Reg_VBinning ] );
+ }
+
+}
+
+// Start flushing the entire CCD (rows = -1) or a specific number or rows
+void CCameraIO::Flush( short Rows )
+{
+ if ( Rows == 0 ) return;
+
+ unsigned short AIC = (unsigned short) ( m_Columns - m_BIC - m_ImgColumns );
+ unsigned short Pixels = (unsigned short) ( m_ImgColumns / m_HFlush );
+ if ( m_ImgColumns % m_HFlush > 0 ) Pixels++; // round up if necessary
+ LoadColumnLayout( AIC, (unsigned short) m_BIC, Pixels );
+
+ LoadTimerAndBinning( 0.0, m_HFlush, m_VFlush );
+
+ if ( Rows > 0 )
+ {
+ LoadLineCounter( (unsigned short) Rows );
+ StartFlushing();
+
+ /////////////////////////////////////
+ // Wait until camera is done flushing
+ clock_t StopTime = clock() + long( m_Timeout * CLOCKS_PER_SEC ); // wait at most m_Timeout seconds
+ while ( true )
+ {
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( ( val & RegBit_FrameDone ) != 0 ) break;
+
+ if ( clock() > StopTime ) break; // Timed out
+ }
+ }
+ else
+ {
+ LoadLineCounter( (unsigned short) m_ImgRows );
+ StartFlushing();
+ }
+}
+
+void CCameraIO::StartFlushing()
+{
+ /////////////////////////////////////
+ // Start flushing
+ m_RegShadow[ Reg_Command ] |= RegBit_StartFlushing; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_StartFlushing;// set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+}
+
+void CCameraIO::StopFlushing()
+{
+ /////////////////////////////////////
+ // Stop flushing
+ m_RegShadow[ Reg_Command ] |= RegBit_StopFlushing; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_StopFlushing; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+}
+
+
+
+
+
diff --git a/kstars/kstars/indi/apogee/CameraIO_Linux.h b/kstars/kstars/indi/apogee/CameraIO_Linux.h
new file mode 100644
index 00000000..d6a61e1c
--- /dev/null
+++ b/kstars/kstars/indi/apogee/CameraIO_Linux.h
@@ -0,0 +1,416 @@
+// CameraIO.h: interface for the CCameraIO class.
+//
+// Copyright (c) 2000 Apogee Instruments Inc.
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CAMERAIO_H__A2882C82_7CFB_11D4_9155_0060676644C1__INCLUDED_)
+#define AFX_CAMERAIO_H__A2882C82_7CFB_11D4_9155_0060676644C1__INCLUDED_
+
+#include "Apogee.h"
+
+enum Camera_Interface{
+ Camera_Interface_ISA = 0,
+ Camera_Interface_PPI,
+ Camera_Interface_PCI
+};
+
+enum Camera_SensorType{
+ Camera_SensorType_CCD = 0,
+ Camera_SensorType_CMOS
+};
+
+const long MAXCOLUMNS = 16383;
+const long MAXROWS = 16383;
+const long MAXHBIN = 8;
+const long MAXVBIN = 255;
+
+// Number of write only registers
+const long NumWriteRegisters = 8;
+
+const long RegISA_Command = 0x000; // Register 1 in ISA firmware
+const long Reg_Command = 0; // Register 1 shadow
+const unsigned short RegBit_TDIMode = 0x1; // Bit 0
+const unsigned short RegBit_StartTimer = 0x2; // Bit 1
+const unsigned short RegBit_ShutterOverride = 0x4; // Bit 2
+const unsigned short RegBit_ResetSystem = 0x8; // Bit 3
+const unsigned short RegBit_FIFOCache = 0x10; // Bit 4
+const unsigned short RegBit_TriggerEnable = 0x20; // Bit 5
+const unsigned short RegBit_StopFlushing = 0x40; // Bit 6
+const unsigned short RegBit_ShutterEnable = 0x80; // Bit 7
+const unsigned short RegBit_CoolerShutdown = 0x100; // Bit 8
+const unsigned short RegBit_DoneReading = 0x200; // Bit 9
+const unsigned short RegBit_TimerLoad = 0x400; // Bit 10
+const unsigned short RegBit_StartNextLine = 0x800; // Bit 11
+const unsigned short RegBit_StartFlushing = 0x1000; // Bit 12
+const unsigned short RegBit_Focus = 0x2000; // Bit 13
+const unsigned short RegBit_CableLength = 0x4000; // Bit 14
+const unsigned short RegBit_CoolerEnable = 0x8000; // Bit 15
+
+const long RegISA_Timer = 0x002; // Register 2 in ISA firmware
+const long Reg_Timer = 1; // Register 2 shadow
+const unsigned short RegBitShift_Timer = 0; // Bit 0
+const unsigned short RegBitMask_Timer = 0xFFFF; // 16 bits
+
+const long RegISA_VBinning = 0x004; // Register 3 in ISA firmware
+const long Reg_VBinning = 2; // Register 3 shadow
+const unsigned short RegBitShift_Timer2 = 0; // Bit 0
+const unsigned short RegBitMask_Timer2 = 0xF; // 4 bits
+const unsigned short RegBitShift_VBinning = 0x8; // Bit 8
+const unsigned short RegBitMask_VBinning = 0xFF; // 8 bits
+
+const long RegISA_AICCounter = 0x006; // Register 4 in ISA firmware
+const long Reg_AICCounter = 3; // Register 4 shadow
+const unsigned short RegBitShift_AICCounter = 0; // Bit 0
+const unsigned short RegBitMask_AICCounter = 0xFFF; // 12 bits
+const unsigned short RegBitShift_Test2 = 0xC; // Bit 12
+const unsigned short RegBitMask_Test2 = 0xF; // 4 bits
+
+const long RegISA_TempSetPoint = 0x008; // Register 5 in ISA firmware
+const long Reg_TempSetPoint = 4; // Register 5 shadow
+const unsigned short RegBitShift_TempSetPoint = 0; // Bit 0
+const unsigned short RegBitMask_TempSetPoint = 0xFF;// 8 bits
+const unsigned short RegBitShift_PortControl = 0x8; // Bit 8
+const unsigned short RegBitMask_PortControl = 0xFF; // 8 bits
+
+const long RegISA_PixelCounter = 0x00a; // Register 6 in ISA firmware
+const long Reg_PixelCounter = 5; // Register 6 shadow
+const unsigned short RegBitShift_PixelCounter = 0; // Bit 0
+const unsigned short RegBitMask_PixelCounter = 0xFFF; // 12 bits
+const unsigned short RegBitShift_HBinning = 0xC; // Bit 12
+const unsigned short RegBitMask_HBinning = 0x7; // 3 bits
+const unsigned short RegBit_LoopLock = 0x8000; // Bit 15
+
+const long RegISA_LineCounter = 0x00c; // Register 7 in ISA firmware
+const long Reg_LineCounter = 6; // Register 7 shadow
+const unsigned short RegBitShift_LineCounter = 0; // Bit 0
+const unsigned short RegBitMask_LineCounter = 0xFFF; // 12 bits
+const unsigned short RegBitShift_Mode = 0xC; // Bit 12
+const unsigned short RegBitMask_Mode = 0xF; // 4 bits
+
+const long RegISA_BICCounter = 0x00e; // Register 8 in ISA firmware
+const long Reg_BICCounter = 7; // Register 8 shadow
+const unsigned short RegBitShift_BICCounter = 0; // Bit 0
+const unsigned short RegBitMask_BICCounter = 0xFFF; // 12 bits
+const unsigned short RegBitShift_Test = 0xC; // Bit 12
+const unsigned short RegBitMask_Test = 0xF; // 4 bits
+
+const long RegISA_ImageData = 0x000; // Register 9 in ISA firmware
+const long Reg_ImageData = 8; // Register 9
+const unsigned short RegBitShift_ImageData = 0; // Bit 0
+const unsigned short RegBitMask_ImageData = 0xFFFF; // 16 bits
+
+const long RegISA_TempData = 0x002; // Register 10 in ISA firmware
+const long Reg_TempData = 9; // Register 10
+const unsigned short RegBitShift_TempData = 0; // Bit 0
+const unsigned short RegBitMask_TempData = 0xFF; // 8 bits
+
+const long RegISA_Status = 0x006; // Register 11 in firmware
+const long Reg_Status = 10; // Register 11
+const unsigned short RegBit_Exposing = 0x1; // Bit 0
+const unsigned short RegBit_LineDone = 0x2; // Bit 1
+const unsigned short RegBit_CacheReadOK = 0x4; // Bit 2
+const unsigned short RegBit_TempAtMin = 0x10; // Bit 4
+const unsigned short RegBit_TempAtMax = 0x20; // Bit 5
+const unsigned short RegBit_ShutdownComplete = 0x40;// Bit 6
+const unsigned short RegBit_TempAtSetPoint = 0x80; // Bit 7
+const unsigned short RegBit_GotTrigger = 0x400; // Bit 10
+const unsigned short RegBit_FrameDone = 0x800; // Bit 11
+const unsigned short RegBit_LoopbackTest = 0x8000; // Bit 15
+
+const long RegISA_CommandReadback = 0x008; // Register 12 in ISA firmware
+const long Reg_CommandReadback = 11; // Register 12
+// Use RegBit offsets from Reg_Command
+
+const long RegPCI_Command = 0x000; // Register 1 in PCI firmware
+const long RegPCI_CommandRead = 0x020;
+const long RegPCI_Timer = 0x004; // Register 2 in PCI firmware
+const long RegPCI_TimerRead = 0x024;
+const long RegPCI_VBinning = 0x008; // Register 3 in PCI firmware
+const long RegPCI_VBinningRead = 0x028;
+const long RegPCI_AICCounter = 0x00C; // Register 4 in PCI firmware
+const long RegPCI_AICCounterRead = 0x02C;
+const long RegPCI_TempSetPoint = 0x010; // Register 5 in PCI firmware
+const long RegPCI_TempSetPointRead = 0x030;
+const long RegPCI_PixelCounter = 0x014; // Register 6 in PCI firmware
+const long RegPCI_PixelCounterRead = 0x034;
+const long RegPCI_LineCounter = 0x018; // Register 7 in PCI firmware
+const long RegPCI_LineCounterRead = 0x038;
+const long RegPCI_BICCounter = 0x01C; // Register 8 in PCI firmware
+const long RegPCI_BICCounterRead = 0x03C;
+const long RegPCI_ImageData = 0x000; // Register 9 in PCI firmware
+const long RegPCI_TempData = 0x004; // Register 10 in PCI firmware
+const long RegPCI_Status = 0x00C; // Register 11 in firmware
+const long RegPCI_CommandReadback = 0x010; // Register 12 in PCI firmware
+
+
+
+class CCameraIO
+{
+public:
+
+ CCameraIO();
+ virtual ~CCameraIO();
+
+ ////////////////////////////////////////////////////////////
+ // Low level read write methods - Overridables
+ bool InitDriver(unsigned short camnum);
+ long ReadLine( long SkipPixels, long Pixels, unsigned short* pLineBuffer );
+ long Write( unsigned short reg, unsigned short val );
+ long Read( unsigned short reg, unsigned short& val );
+
+ ////////////////////////////////////////////////////////////
+ // Camera Settings
+
+ Camera_Status read_Status(); // Current camera state
+ // <0: error codes
+ // 0: idle
+ // 1: flushing
+ // 2: waiting for trigger
+ // 3: exposing
+ // 4: reading
+ // 5: downloading
+ // 6: line ready
+ // 7: image ready
+
+ bool read_Present(); // True if camera is present, false otherwise.
+
+ bool read_Shutter(); // Current shutter state, true = open, false = closed.
+ void write_Shutter( bool val );
+
+ bool read_ForceShutterOpen(); // True: Forces shutter permanently open. False: allows
+ void write_ForceShutterOpen( bool val ); // normal shutter operation.
+
+ bool read_LongCable(); // Long cable mode.
+ void write_LongCable( bool val );
+
+ short read_Mode(); // First four bits map to Mode bits used for
+ void write_Mode( short val ); // special functions or camera configurations.
+
+ short read_TestBits(); // First four bits to Test bits used for
+ void write_TestBits( short val ); // troubleshooting.
+
+ short read_Test2Bits(); // First four bits map to Test2 bits used for
+ void write_Test2Bits( short val ); // special functions or camera configurations.
+
+ bool read_FastReadout(); // Fast readout mode (used for focusing).
+ void write_FastReadout( bool val ); // True means fast focus is on
+
+ bool read_UseTrigger(); // Triggered exposure mode.
+ void write_UseTrigger( bool val ); // True means triggered exposure is on.
+
+ bool m_HighPriority; // Bost thread priority level during download
+
+ short m_PPRepeat; // Delay used on parallel port systems.
+
+ short m_DataBits; // Digitization resolution, 8 - 18.
+
+ bool m_FastShutter; // Capable of 0.001 sec exposure resolution
+
+ bool m_GuiderRelays; // Capable of outputing autoguider signals
+
+ short m_MaxBinX, m_MaxBinY; // Maximum binning factors
+
+ double m_MaxExposure; // Maximum exposure length
+ double m_MinExposure; // Minimum exposure length
+
+ double m_Timeout; // camera polling timeout value
+
+ ////////////////////////////////////////////////////////////
+ // Cooler Settings
+ // N.B. DAC units = ( m_TempScale * CoolerSetPoint (deg. C ) ) + m_TempCalibration;
+ // N.B. Temperature (deg. C) = (DAC units - m_TempCalibration) / m_TempScale
+
+ double read_CoolerSetPoint(); // Returns/sets setpoint temperature in degrees
+ void write_CoolerSetPoint( double val ); // Celcius.
+
+ Camera_CoolerStatus read_CoolerStatus(); // Returns current cooler status
+
+ Camera_CoolerMode read_CoolerMode(); // Returns/sets current cooler operation mode.
+ void write_CoolerMode( Camera_CoolerMode val );
+
+ double read_Temperature(); // Current temperature in degrees Celcius.
+
+ bool m_TempControl; // Temperature can be externally controlled
+ short m_TempCalibration; // Temperature calibration factor.
+ double m_TempScale; // Temperature scaling factor.
+
+ ////////////////////////////////////////////////////////////
+ // Exposure Settings
+ // The following variables are latched in Expose method, until next Reset or GetImage
+
+ short m_BinX, m_BinY; // Horizontal and vertical binning.
+ short m_StartX, m_StartY; // Zero based subframe start position in unbinned pixels.
+ short m_NumX, m_NumY; // Subframe size in binned pixels.
+
+ ////////////////////////////////////////////////////////////
+ // Geometry Settings
+ // The following variables are latched in Expose method, until next Reset or GetImage
+
+ short m_Columns, m_Rows; // Total columns/rows on CCD (physical).
+ short m_ImgColumns, m_ImgRows; // Unbinned columns/rows in imaging area
+ short m_SkipC, m_SkipR; // Deleted data columns/rows not to be displayed or saved
+ short m_HFlush, m_VFlush; // Horizontal/Vertical flush binning.
+ short m_BIC, m_BIR; // Before Image Column/Row count (dark non-imaging pixels).
+
+ ////////////////////////////////////////////////////////////
+ // CCD Settings
+
+ char m_Sensor[ 256 ]; // Sensor model installed in camera (i.e. Sensor = SITe 502).
+ bool m_Color; // Sensor has color dyes
+ double m_Noise; // Read out noise in e-.
+ double m_Gain; // Gain in e-/ADU units.
+ double m_PixelXSize; // Size of pixel in X direction in micrometers.
+ double m_PixelYSize; // Size of pixel in Y direction in micrometers.
+
+ ////////////////////////////////////////////////////////////
+ // System methods
+
+ // Resets camera to idle state, will terminate current exposure.
+ void Reset();
+
+ // Mask user requested set of IRQS
+// void MaskIrqs();
+
+ // Restore default IRQ mask
+// void UnmaskIrqs();
+
+ // Starts flushing the camera (which should be the normal idle state)
+ // If Rows is non-negative, only the specified number of rows are flushed,
+ // in which case the method will return only when flushing is completed.
+ void Flush( short Rows = -1 );
+
+ // Output byte to auxillary output port (e.g. for driving guider relays).
+ void AuxOutput( unsigned char val );
+
+ // Write a 16 bit value to register 1 to 8.
+ void RegWrite( short reg, unsigned short val );
+
+ // Read a 16 bit value from register 9 to 12.
+ void RegRead( short reg, unsigned short& val );
+
+ // Move the filterwheel to the home position - failure indicates no filterwheel
+ //attached or broken filterwheel
+ bool FilterHome();
+
+ // Move filterwheel to the given slot
+ void FilterSet( short Slot );
+
+ ////////////////////////////////////////////////////////////
+ // Normal exposure methods
+
+ // The Duration parameter is the exposure time in seconds. The Light parameter controls
+ // the status of the shutter during the exposure, Light = True opens the shutter, Light
+ // = False closes the shutter. Returns immediately after invocation, poll the CameraStatus
+ // property to determine the start time of a triggered exposure and the end of an exposure.
+ bool Expose( double Duration, bool Light );
+
+ // Returns the pImageData parameter which is a pointer to unsigned short data with NumX*NumY
+ // elements. Can be overridden if necessary
+ virtual bool GetImage( unsigned short* pImageData, short& xSize, short& ySize );
+
+ /*virtual bool BufferImage(char *bufferName );*/
+
+ ////////////////////////////////////////////////////////////
+ // Drift scan methods
+
+ // Begins clocking and digitization of a single line of data begining with a vertical clock
+ // sequence and ending with a buffer full of line data. Poll the CameraStatus property to
+ // determine when the data is ready for download.
+ bool DigitizeLine();
+
+ // Returns the pLineData parameter which is a pointer to unsigned short data with NumX elements.
+ bool GetLine( unsigned short* pLineData, short& xSize );
+
+ /* TODO enable this back after removing some deps */
+ /*bool BufferDriftScan(char *bufferName, int delay, int rowCount, int nblock , int npipe);*/
+
+ ////////////////////////////////////////////////////////////
+ // Easy to use methods
+
+ // Combination of the Expose and GetImage methods. Blocks calling thread for duration
+ // of exposure and readout.
+ bool Snap( double Duration, bool Light, unsigned short* pImageData, short& xSize, short& ySize );
+
+// Internal variables to keep track of things that can not be read from the firmware
+// directly, or are a combination of firmware setting
+
+ bool m_TDI; // Time drift integration mode
+
+ bool m_WaitingforTrigger; // camera is waiting for external trigger
+ bool m_WaitingforImage; // camera is exposing and wiating for an to available
+ bool m_WaitingforLine; // camera is clocking and digitizing a row of data
+
+ short m_RegisterOffset; // Offset from base address used in parallel port systems.
+
+ short m_FilterPosition; // Current filter position
+ short m_FilterStepPos; // Current filter position in our internal array
+
+ bool m_Shutter; // Last known shutter state
+ Camera_Status m_Status; // Last known camera status
+
+ Camera_Interface m_Interface; // String acronyms may be used in INI file.
+ // 0 or ISA: Industry Standard Architecture bus
+ // 1 or PPI: Parallel Port Interface
+ // 2 or PCI: Peripheral Component Interface
+
+ Camera_SensorType m_SensorType; // 0 or CCD: Charge Coupled Device
+ // 1 or CMOS: Complementary Metal-Oxide-Silicon
+
+ Camera_CoolerStatus m_CoolerStatus; // Last known cooler status.
+ unsigned int m_IRQMask; // Set of IRQs masked on user request // 0: Off
+ // 1: Ramping to set point
+ // 2: Correcting
+ // 3: Ramping to ambient
+ // 4: At ambient
+ // 5: Max cooling limit
+ // 6: Min cooling limit
+ // 7: At set point
+
+ // Latched public variables used during Exposure..GetImage sequence
+ short m_ExposureBinX, m_ExposureBinY; // Horizontal and vertical binning.
+ short m_ExposureStartX, m_ExposureStartY; // Subframe start position in unbinned pixels.
+ short m_ExposureNumX, m_ExposureNumY; // Subframe size in binned pixels.
+ short m_ExposureColumns, m_ExposureRows; // Total columns/rows on CCD (physical).
+ short m_ExposureSkipC, m_ExposureSkipR; // Deleted data columns/rows not to be displayed or saved to disk.
+ short m_ExposureHFlush, m_ExposureVFlush; // Horizontal/Vertical flush binning.
+ short m_ExposureBIC, m_ExposureBIR; // Before Image Column/Row count (dark non-imaging pixels).
+ unsigned short m_ExposureAIC; // Calculated After Image Column count (dark non-imaging pixels).
+ unsigned short m_ExposureRemainingLines; // Number of lines to be clocked out by GetImage
+ unsigned short m_ExposureAIR; // Number of lines to be flushed after GetImage
+
+ ////////////////////////////////////////////////////////////
+ // Write register shadow variables
+ unsigned short m_RegShadow[ NumWriteRegisters ];
+
+ unsigned short m_FastShutterBits_Mode; // Mask to enable fast shutter mode
+ unsigned short m_FastShutterBits_Test; // Mask to enable fast shutter mode
+
+ ////////////////////////////////////////////////////////////
+ // Internal helper routines
+
+ void LoadLineCounter( unsigned short rows );
+ void LoadColumnLayout( unsigned short aic, unsigned short bic, unsigned short pixels );
+ void LoadTimerAndBinning( double Duration, unsigned short HBin, unsigned short VBin );
+
+ void StartFlushing();
+ void StopFlushing();
+
+ void InitDefaults();
+#ifndef WITHPPI
+long ReadImage(short unsigned int *);
+long InternalReadLine(bool, long int, long int, unsigned short *);
+#endif
+
+private:
+ unsigned short m_BaseAddressp2;
+ unsigned int saveIRQS;
+ int fileHandle;
+#ifdef WITHPPI
+ inline void RegisterSelect( unsigned short reg );
+ inline unsigned short INPW();
+ inline void OUTPW( unsigned short val );
+#endif
+
+};
+
+#endif // !defined(AFX_CAMERAIO_H__A2882C82_7CFB_11D4_9155_0060676644C1__INCLUDED_)
diff --git a/kstars/kstars/indi/apogee/CameraIO_LinuxISA.cpp b/kstars/kstars/indi/apogee/CameraIO_LinuxISA.cpp
new file mode 100644
index 00000000..16a6bb72
--- /dev/null
+++ b/kstars/kstars/indi/apogee/CameraIO_LinuxISA.cpp
@@ -0,0 +1,319 @@
+// CameraIO.cpp: implementation of the CCameraIO class.
+//
+// Copyright (c) 2000 Apogee Instruments Inc.
+//////////////////////////////////////////////////////////////////////
+
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <sched.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#define HANDLE int
+#define FALSE 0
+#define DWORD long
+#define _ASSERT assert
+#define REALTIME_PRIORITY_CLASS 1
+#define GetCurrentProcess getpid
+#define LOBYTE(x) ((x) & 0xff)
+#define HIBYTE(x) ((x >> 8) & 0xff)
+
+#define MIRQ1 0x21
+#define MIRQ2 0xA1
+
+#include "time.h"
+//#include "tcl.h"
+//#include "ccd.h"
+#include "CameraIO_Linux.h"
+#include "ApogeeLinux.h"
+
+const int NUM_POSITIONS = 6;
+const int NUM_STEPS_PER_FILTER = 48;
+const int STEP_DELAY = 10;
+
+const unsigned char Steps[] = { 0x10, 0x30, 0x20, 0x60, 0x40, 0xc0, 0x80, 0x90 };
+const int NUM_STEPS = sizeof ( Steps );
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+void CCameraIO::InitDefaults()
+{
+ ////////////////////////////////////////////////////////////
+ // Camera Settings
+
+ m_HighPriority = true;
+ m_PPRepeat = 1;
+ m_DataBits = 16;
+ m_FastShutter = false;
+ m_MaxBinX = 8;
+ m_MaxBinY = 63;
+ m_MaxExposure = 10485.75;
+ m_MinExposure = 0.01;
+ m_GuiderRelays = false;
+ m_Timeout = 2.0;
+
+ ////////////////////////////////////////////////////////////
+ // Cooler Settings
+
+ m_TempControl = true;
+ m_TempCalibration = 160;
+ m_TempScale = 2.1;
+
+ ////////////////////////////////////////////////////////////
+ // Exposure Settings
+
+ m_BinX = 1;
+ m_BinY = 1;
+ m_StartX = 0;
+ m_StartY = 0;
+ m_NumX = 1;
+ m_NumY = 1;
+
+ ////////////////////////////////////////////////////////////
+ // Geometry Settings
+
+ m_Columns = 0;
+ m_Rows = 0;
+ m_SkipC = 0;
+ m_SkipR = 0;
+ m_HFlush = 1;
+ m_VFlush = 1;
+ m_BIC = 4;
+ m_BIR = 4;
+ m_ImgColumns = 0;
+ m_ImgRows = 0;
+
+ ////////////////////////////////////////////////////////////
+ // CCD Settings
+
+ memset( m_Sensor, 0, 256 );
+ m_Color = false;
+ m_Noise = 0.0;
+ m_Gain = 0.0;
+ m_PixelXSize = 0.0;
+ m_PixelYSize = 0.0;
+
+ ////////////////////////////////////////////////////////////
+ // Internal variables
+
+ fileHandle = 0;
+ m_RegisterOffset = 0;
+ m_Interface = Camera_Interface_ISA;
+ m_SensorType = Camera_SensorType_CCD;
+}
+
+
+
+bool CCameraIO::InitDriver(unsigned short camnum)
+{
+ char deviceName[64];
+
+ sprintf(deviceName,"%s%d",APOGEE_ISA_DEVICE,camnum);
+ fileHandle = ::open(deviceName,O_RDONLY);
+ if (fileHandle == -1) return false;
+ return true;
+}
+
+long CCameraIO::Write( unsigned short reg, unsigned short val )
+{
+ int status;
+
+ struct apIOparam request;
+ unsigned short realreg = ( reg << 1 ) & 0xE; // limit input to our address range
+ request.reg = realreg;
+ request.param1=(int)val;
+ status=ioctl(fileHandle,APISA_WRITE_USHORT,(unsigned long)&request);
+ return 0;
+}
+
+long CCameraIO::Read( unsigned short reg, unsigned short& val )
+{
+ unsigned short realreg;
+ int retval, status;
+ struct apIOparam request;
+
+ switch ( reg )
+ {
+ case Reg_ImageData:
+ realreg = RegISA_ImageData;
+ break;
+ case Reg_TempData:
+ realreg = RegISA_TempData;
+ break;
+ case Reg_Status:
+ realreg = RegISA_Status;
+ break;
+ case Reg_CommandReadback:
+ realreg = RegISA_CommandReadback;
+ break;
+ default:
+ assert( 1 ); // application program bug
+ val = 0;
+ return 0;
+ }
+
+ request.reg = realreg;
+ request.param1=(unsigned long)&retval;
+ status=ioctl(fileHandle,APISA_READ_USHORT,(unsigned long)&request);
+ val = (unsigned short)retval;
+ return 0;
+}
+
+// Returns 0 if successfull, 1 if Line_Done poll timed out.
+long CCameraIO::ReadLine( long SkipPixels, long Pixels,unsigned short* pLineBuffer )
+{
+ int j;
+ int retval, status;
+ struct apIOparam request;
+
+ if ( !m_TDI )
+ {
+ /////////////////////////////////////
+ // Clock out the line
+ m_RegShadow[ Reg_Command ] |= RegBit_StartNextLine; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_StartNextLine; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+ }
+
+ request.reg = RegISA_ImageData;
+ request.param1=(unsigned long)&retval;
+
+ for (j = 0; j < SkipPixels; j++)
+ {
+ status=ioctl(fileHandle,APISA_READ_USHORT,(unsigned long)&request);
+ }
+ for (j = 0; j < Pixels; j++)
+ {
+ status=ioctl(fileHandle,APISA_READ_USHORT,(unsigned long)&request);
+ *pLineBuffer++ = (unsigned short)retval;
+ }
+ /////////////////////////////////////
+ // Assert done reading line
+ m_RegShadow[ Reg_Command ] |= RegBit_DoneReading; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_DoneReading; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+
+ if ( !m_TDI )
+ {
+ /////////////////////////////////////
+ // Wait until camera is done
+ clock_t StopTime = clock() + CLOCKS_PER_SEC; // wait at most one second
+ while ( true )
+ {
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( ( val & RegBit_LineDone ) != 0 ) break;// Line done
+
+ if ( clock() > StopTime ) return 1; // Timed out
+ }
+ }
+
+ return 0;
+}
+
+
+
+long CCameraIO::ReadImage( unsigned short* pImageBuffer )
+{
+ m_RegShadow[ Reg_Command ] |= RegBit_FIFOCache; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ long XEnd = long( m_ExposureNumX );
+ long SkipC = long( m_ExposureSkipC );
+ for (long i = 0; i < m_ExposureSkipR; i++)
+ {
+ if( InternalReadLine( false, SkipC, XEnd, NULL ) ) return 1;
+ }
+
+ long YEnd = long( m_ExposureNumY );
+ unsigned short* pLineBuffer = pImageBuffer;
+ for (long i = 0; i < YEnd; i++)
+ {
+ if ( InternalReadLine( true, SkipC, XEnd, pLineBuffer ) ) return 1;
+ pLineBuffer += XEnd;
+ }
+
+ m_RegShadow[ Reg_Command ] &= !RegBit_FIFOCache; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ return 0;
+}
+
+
+
+// Returns 0 if successfull, 1 if Line_Done poll timed out.
+long CCameraIO::InternalReadLine( bool KeepData, long SkipC, long XEnd, unsigned short* pLineBuffer )
+{
+ struct apIOparam request;
+ int retval, status;
+
+ /////////////////////////////////////
+ // Clock out the line
+ m_RegShadow[ Reg_Command ] |= RegBit_StartNextLine; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= !RegBit_StartNextLine; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+
+ request.reg = RegISA_ImageData;
+ request.param1=(unsigned long)&retval;
+
+ for (long j = 0; j < SkipC; j++)
+ status=ioctl(fileHandle,APISA_READ_USHORT,(unsigned long)&request);
+
+ if ( KeepData )
+ {
+ for (long j = 0; j < XEnd; j++) {
+ status=ioctl(fileHandle,APISA_READ_USHORT,(unsigned long)&request);
+ *pLineBuffer++ = (unsigned short)retval;
+ }
+ }
+ else
+ {
+ for (long j = 0; j < XEnd; j++)
+ status=ioctl(fileHandle,APISA_READ_USHORT,(unsigned long)&request);
+ }
+
+ /////////////////////////////////////
+ // Assert done reading line
+ m_RegShadow[ Reg_Command ] |= RegBit_DoneReading; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= !RegBit_DoneReading; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+
+ /////////////////////////////////////
+ // Wait until camera is done clocking
+ clock_t StopTime = clock() + CLOCKS_PER_SEC; // wait at most one second
+ while ( true )
+ {
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( ( val & RegBit_LineDone ) != 0 ) break;// Line done
+
+ clock_t CurrentTime = clock();
+ if ( CurrentTime > StopTime ) return 1; // Timed out
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/kstars/kstars/indi/apogee/CameraIO_LinuxPCI.cpp b/kstars/kstars/indi/apogee/CameraIO_LinuxPCI.cpp
new file mode 100644
index 00000000..a83a594e
--- /dev/null
+++ b/kstars/kstars/indi/apogee/CameraIO_LinuxPCI.cpp
@@ -0,0 +1,373 @@
+// CameraIO.cpp: implementation of the CCameraIO class.
+//
+// Copyright (c) 2000 Apogee Instruments Inc.
+//////////////////////////////////////////////////////////////////////
+
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <sched.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#define HANDLE int
+#define FALSE 0
+#define DWORD long
+#define _ASSERT assert
+#define REALTIME_PRIORITY_CLASS 1
+#define GetCurrentProcess getpid
+#define LOBYTE(x) ((x) & 0xff)
+#define HIBYTE(x) ((x >> 8) & 0xff)
+
+#define MIRQ1 0x21
+#define MIRQ2 0xA1
+
+#include "time.h"
+//#include "tcl.h"
+//#include "ccd.h"
+#include "CameraIO_Linux.h"
+#include "ApogeeLinux.h"
+
+const int NUM_POSITIONS = 6;
+const int NUM_STEPS_PER_FILTER = 48;
+const int STEP_DELAY = 10;
+
+const unsigned char Steps[] = { 0x10, 0x30, 0x20, 0x60, 0x40, 0xc0, 0x80, 0x90 };
+const int NUM_STEPS = sizeof ( Steps );
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+void CCameraIO::InitDefaults()
+{
+ ////////////////////////////////////////////////////////////
+ // Camera Settings
+
+ m_HighPriority = true;
+ m_PPRepeat = 1;
+ m_DataBits = 16;
+ m_FastShutter = false;
+ m_MaxBinX = 8;
+ m_MaxBinY = 63;
+ m_MaxExposure = 10485.75;
+ m_MinExposure = 0.01;
+ m_GuiderRelays = false;
+ m_Timeout = 2.0;
+
+ ////////////////////////////////////////////////////////////
+ // Cooler Settings
+
+ m_TempControl = true;
+ m_TempCalibration = 160;
+ m_TempScale = 2.1;
+
+ ////////////////////////////////////////////////////////////
+ // Exposure Settings
+
+ m_BinX = 1;
+ m_BinY = 1;
+ m_StartX = 0;
+ m_StartY = 0;
+ m_NumX = 1;
+ m_NumY = 1;
+
+ ////////////////////////////////////////////////////////////
+ // Geometry Settings
+
+ m_Columns = 0;
+ m_Rows = 0;
+ m_SkipC = 0;
+ m_SkipR = 0;
+ m_HFlush = 1;
+ m_VFlush = 1;
+ m_BIC = 4;
+ m_BIR = 4;
+ m_ImgColumns = 0;
+ m_ImgRows = 0;
+
+ ////////////////////////////////////////////////////////////
+ // CCD Settings
+
+ memset( m_Sensor, 0, 256 );
+ m_Color = false;
+ m_Noise = 0.0;
+ m_Gain = 0.0;
+ m_PixelXSize = 0.0;
+ m_PixelYSize = 0.0;
+
+ ////////////////////////////////////////////////////////////
+ // Internal variables
+
+ fileHandle = 0;
+ m_RegisterOffset = 0;
+ m_Interface = Camera_Interface_PCI;
+ m_SensorType = Camera_SensorType_CCD;
+}
+
+
+
+bool CCameraIO::InitDriver(unsigned short camnum)
+{
+ char deviceName[64];
+
+ sprintf(deviceName,"%s%d",APOGEE_PCI_DEVICE,camnum);
+ fileHandle = ::open(deviceName,O_RDONLY);
+ if (fileHandle == -1) return false;
+ return true;
+}
+
+long CCameraIO::Write( unsigned short reg, unsigned short val )
+{
+ int status;
+ unsigned short RegNumber;
+ struct apIOparam request;
+
+ switch ( reg )
+ {
+ case Reg_Command:
+ RegNumber = RegPCI_Command;
+ break;
+ case Reg_Timer:
+ RegNumber = RegPCI_Timer;
+ break;
+ case Reg_VBinning:
+ RegNumber = RegPCI_VBinning;
+ break;
+ case Reg_AICCounter:
+ RegNumber = RegPCI_AICCounter;
+ break;
+ case Reg_TempSetPoint:
+ RegNumber = RegPCI_TempSetPoint;
+ break;
+ case Reg_PixelCounter:
+ RegNumber = RegPCI_PixelCounter;
+ break;
+ case Reg_LineCounter:
+ RegNumber = RegPCI_LineCounter;
+ break;
+ case Reg_BICCounter:
+ RegNumber = RegPCI_BICCounter;
+ break;
+ default:
+ _ASSERT ( false );
+ return 0;
+ }
+ request.reg = RegNumber;
+ request.param1=(int)val;
+ status=ioctl(fileHandle,APPCI_WRITE_USHORT,(unsigned long)&request);
+ return 0;
+}
+
+long CCameraIO::Read( unsigned short reg, unsigned short& val )
+{
+ int retval, status;
+ struct apIOparam request;
+ unsigned short RegNumber;
+
+ switch ( reg )
+ {
+ case Reg_Command:
+ RegNumber = RegPCI_CommandRead;
+ break;
+ case Reg_Timer:
+ RegNumber = RegPCI_TimerRead;
+ break;
+ case Reg_VBinning:
+ RegNumber = RegPCI_VBinningRead;
+ break;
+ case Reg_AICCounter:
+ RegNumber = RegPCI_AICCounterRead;
+ break;
+ case Reg_TempSetPoint:
+ RegNumber = RegPCI_TempSetPointRead;
+ break;
+ case Reg_PixelCounter:
+ RegNumber = RegPCI_PixelCounterRead;
+ break;
+ case Reg_LineCounter:
+ RegNumber = RegPCI_LineCounterRead;
+ break;
+ case Reg_BICCounter:
+ RegNumber = RegPCI_BICCounterRead;
+ break;
+ case Reg_ImageData:
+ RegNumber = RegPCI_ImageData;
+ break;
+ case Reg_TempData:
+ RegNumber = RegPCI_TempData;
+ break;
+ case Reg_Status:
+ RegNumber = RegPCI_Status;
+ break;
+ case Reg_CommandReadback:
+ RegNumber = RegPCI_CommandReadback;
+ break;
+ default:
+ assert( 1 ); // application program bug
+ val = 0;
+ return 0;
+ }
+
+ request.reg = RegNumber;
+ request.param1=(unsigned long)&retval;
+ status=ioctl(fileHandle,APPCI_READ_USHORT,(unsigned long)&request);
+ val = (unsigned short)retval;
+ return 0;
+}
+
+// Returns 0 if successfull, 1 if Line_Done poll timed out.
+long CCameraIO::ReadLine( long SkipPixels, long Pixels,unsigned short* pLineBuffer )
+{
+ int j;
+ int retval, status;
+ struct apIOparam request;
+
+ if ( !m_TDI )
+ {
+ /////////////////////////////////////
+ // Clock out the line
+ m_RegShadow[ Reg_Command ] |= RegBit_StartNextLine; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_StartNextLine; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+ }
+
+ request.reg = RegPCI_ImageData;
+ request.param1=(unsigned long)&retval;
+
+ for (j = 0; j < SkipPixels; j++)
+ {
+ status=ioctl(fileHandle,APPCI_READ_USHORT,(unsigned long)&request);
+ }
+ for (j = 0; j < Pixels; j++)
+ {
+ status=ioctl(fileHandle,APPCI_READ_USHORT,(unsigned long)&request);
+ *pLineBuffer++ = (unsigned short)retval;
+ }
+ /////////////////////////////////////
+ // Assert done reading line
+ m_RegShadow[ Reg_Command ] |= RegBit_DoneReading; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_DoneReading; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+
+ if ( !m_TDI )
+ {
+ /////////////////////////////////////
+ // Wait until camera is done
+ clock_t StopTime = clock() + CLOCKS_PER_SEC; // wait at most one second
+ while ( true )
+ {
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( ( val & RegBit_LineDone ) != 0 ) break;// Line done
+
+ if ( clock() > StopTime ) return 1; // Timed out
+ }
+ }
+
+ return 0;
+}
+
+
+
+long CCameraIO::ReadImage( unsigned short* pImageBuffer )
+{
+ m_RegShadow[ Reg_Command ] |= RegBit_FIFOCache; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ long XEnd = long( m_ExposureNumX );
+ long SkipC = long( m_ExposureSkipC );
+ for (long i = 0; i < m_ExposureSkipR; i++)
+ {
+ if( InternalReadLine( false, SkipC, XEnd, NULL ) ) return 1;
+ }
+
+ long YEnd = long( m_ExposureNumY );
+ unsigned short* pLineBuffer = pImageBuffer;
+ for (long i = 0; i < YEnd; i++)
+ {
+ if ( InternalReadLine( true, SkipC, XEnd, pLineBuffer ) ) return 1;
+ pLineBuffer += XEnd;
+ }
+
+ m_RegShadow[ Reg_Command ] &= !RegBit_FIFOCache; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ return 0;
+}
+
+
+
+// Returns 0 if successfull, 1 if Line_Done poll timed out.
+long CCameraIO::InternalReadLine( bool KeepData, long SkipC, long XEnd, unsigned short* pLineBuffer )
+{
+ struct apIOparam request;
+ int retval, status;
+
+ /////////////////////////////////////
+ // Clock out the line
+ m_RegShadow[ Reg_Command ] |= RegBit_StartNextLine; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= !RegBit_StartNextLine; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+
+ request.reg = RegPCI_ImageData;
+ request.param1=(unsigned long)&retval;
+
+ for (long j = 0; j < SkipC; j++)
+ status=ioctl(fileHandle,APPCI_READ_USHORT,(unsigned long)&request);
+
+ if ( KeepData )
+ {
+ for (long j = 0; j < XEnd; j++) {
+ status=ioctl(fileHandle,APPCI_READ_USHORT,(unsigned long)&request);
+ *pLineBuffer++ = (unsigned short)retval;
+ }
+ }
+ else
+ {
+ for (long j = 0; j < XEnd; j++)
+ status=ioctl(fileHandle,APPCI_READ_USHORT,(unsigned long)&request);
+ }
+
+ /////////////////////////////////////
+ // Assert done reading line
+ m_RegShadow[ Reg_Command ] |= RegBit_DoneReading; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= !RegBit_DoneReading; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+
+ /////////////////////////////////////
+ // Wait until camera is done clocking
+ clock_t StopTime = clock() + CLOCKS_PER_SEC; // wait at most one second
+ while ( true )
+ {
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( ( val & RegBit_LineDone ) != 0 ) break;// Line done
+
+ clock_t CurrentTime = clock();
+ if ( CurrentTime > StopTime ) return 1; // Timed out
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/kstars/kstars/indi/apogee/CameraIO_LinuxPPI.cpp b/kstars/kstars/indi/apogee/CameraIO_LinuxPPI.cpp
new file mode 100644
index 00000000..7025d9ce
--- /dev/null
+++ b/kstars/kstars/indi/apogee/CameraIO_LinuxPPI.cpp
@@ -0,0 +1,325 @@
+// CameraIO.cpp: implementation of the CCameraIO class.
+//
+// Copyright (c) 2000 Apogee Instruments Inc.
+//////////////////////////////////////////////////////////////////////
+
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <sched.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#define HANDLE int
+#define FALSE 0
+#define DWORD long
+#define _ASSERT assert
+#define REALTIME_PRIORITY_CLASS 1
+#define GetCurrentProcess getpid
+#define LOBYTE(x) ((x) & 0xff)
+#define HIBYTE(x) ((x >> 8) & 0xff)
+
+#define MIRQ1 0x21
+#define MIRQ2 0xA1
+
+#include "time.h"
+//#include "tcl.h"
+//#include "ccd.h"
+
+#include "CameraIO_Linux.h"
+#include "ApogeeLinux.h"
+
+const int NUM_POSITIONS = 6;
+const int NUM_STEPS_PER_FILTER = 48;
+const int STEP_DELAY = 10;
+
+const unsigned char Steps[] = { 0x10, 0x30, 0x20, 0x60, 0x40, 0xc0, 0x80, 0x90 };
+const int NUM_STEPS = sizeof ( Steps );
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+void CCameraIO::InitDefaults()
+{
+ ////////////////////////////////////////////////////////////
+ // Camera Settings
+
+ m_HighPriority = true;
+ m_PPRepeat = 1;
+ m_DataBits = 16;
+ m_FastShutter = false;
+ m_MaxBinX = 8;
+ m_MaxBinY = 63;
+ m_MaxExposure = 10485.75;
+ m_MinExposure = 0.01;
+ m_GuiderRelays = false;
+ m_Timeout = 2.0;
+
+ ////////////////////////////////////////////////////////////
+ // Cooler Settings
+
+ m_TempControl = true;
+ m_TempCalibration = 160;
+ m_TempScale = 2.1;
+
+ ////////////////////////////////////////////////////////////
+ // Exposure Settings
+
+ m_BinX = 1;
+ m_BinY = 1;
+ m_StartX = 0;
+ m_StartY = 0;
+ m_NumX = 1;
+ m_NumY = 1;
+
+ ////////////////////////////////////////////////////////////
+ // Geometry Settings
+
+ m_Columns = 0;
+ m_Rows = 0;
+ m_SkipC = 0;
+ m_SkipR = 0;
+ m_HFlush = 1;
+ m_VFlush = 1;
+ m_BIC = 4;
+ m_BIR = 4;
+ m_ImgColumns = 0;
+ m_ImgRows = 0;
+
+ ////////////////////////////////////////////////////////////
+ // CCD Settings
+
+ memset( m_Sensor, 0, 256 );
+ m_Color = false;
+ m_Noise = 0.0;
+ m_Gain = 0.0;
+ m_PixelXSize = 0.0;
+ m_PixelYSize = 0.0;
+
+ ////////////////////////////////////////////////////////////
+ // Internal variables
+
+ fileHandle = 0;
+ m_RegisterOffset = 0;
+ m_Interface = Camera_Interface_PPI;
+ m_SensorType = Camera_SensorType_CCD;
+}
+
+
+
+bool CCameraIO::InitDriver(unsigned short camnum)
+{
+ char deviceName[64];
+
+ sprintf(deviceName,"%s%d",APOGEE_PPI_DEVICE,camnum);
+ fileHandle = ::open(deviceName,O_RDONLY);
+ if (fileHandle == -1) return false;
+ return true;
+}
+
+long CCameraIO::Write( unsigned short reg, unsigned short val )
+{
+ int status;
+
+ struct apIOparam request;
+ unsigned short realreg = ( reg << 1 ) & 0xE; // limit input to our address range
+ request.reg = realreg;
+ request.param1=(int)val;
+ request.param2=(int)m_PPRepeat;
+ status=ioctl(fileHandle,APPPI_WRITE_USHORT,(unsigned long)&request);
+ return 0;
+}
+
+long CCameraIO::Read( unsigned short reg, unsigned short& val )
+{
+ unsigned short realreg;
+ int retval, status;
+ struct apIOparam request;
+
+ switch ( reg )
+ {
+ case Reg_ImageData:
+ realreg = RegISA_ImageData;
+ break;
+ case Reg_TempData:
+ realreg = RegISA_TempData;
+ break;
+ case Reg_Status:
+ realreg = RegISA_Status;
+ break;
+ case Reg_CommandReadback:
+ realreg = RegISA_CommandReadback;
+ break;
+ default:
+ assert( 1 ); // application program bug
+ val = 0;
+ return 0;
+ }
+
+ request.reg = realreg;
+ request.param1=(unsigned long)&retval;
+ request.param2=(int)m_PPRepeat;
+ status=ioctl(fileHandle,APPPI_READ_USHORT,(unsigned long)&request);
+ val = (unsigned short)retval;
+ return 0;
+}
+
+// Returns 0 if successfull, 1 if Line_Done poll timed out.
+long CCameraIO::ReadLine( long SkipPixels, long Pixels,unsigned short* pLineBuffer )
+{
+ int j;
+ int retval, status;
+ struct apIOparam request;
+
+ if ( !m_TDI )
+ {
+ /////////////////////////////////////
+ // Clock out the line
+ m_RegShadow[ Reg_Command ] |= RegBit_StartNextLine; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_StartNextLine; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+ }
+
+ request.reg = RegISA_ImageData;
+ request.param1=(unsigned long)&retval;
+ request.param2=(int)m_PPRepeat;
+
+ for (j = 0; j < SkipPixels; j++)
+ {
+ status=ioctl(fileHandle,APPPI_READ_USHORT,(unsigned long)&request);
+ }
+ for (j = 0; j < Pixels; j++)
+ {
+ status=ioctl(fileHandle,APPPI_READ_USHORT,(unsigned long)&request);
+ *pLineBuffer++ = (unsigned short)retval;
+ }
+ /////////////////////////////////////
+ // Assert done reading line
+ m_RegShadow[ Reg_Command ] |= RegBit_DoneReading; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_DoneReading; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+
+ if ( !m_TDI )
+ {
+ /////////////////////////////////////
+ // Wait until camera is done
+ clock_t StopTime = clock() + CLOCKS_PER_SEC; // wait at most one second
+ while ( true )
+ {
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( ( val & RegBit_LineDone ) != 0 ) break;// Line done
+
+ if ( clock() > StopTime ) return 1; // Timed out
+ }
+ }
+
+ return 0;
+}
+
+
+
+long CCameraIO::ReadImage( unsigned short* pImageBuffer )
+{
+ m_RegShadow[ Reg_Command ] |= RegBit_FIFOCache; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ long XEnd = long( m_ExposureNumX );
+ long SkipC = long( m_ExposureSkipC );
+ for (long i = 0; i < m_ExposureSkipR; i++)
+ {
+ if( InternalReadLine( false, SkipC, XEnd, NULL ) ) return 1;
+ }
+
+ long YEnd = long( m_ExposureNumY );
+ unsigned short* pLineBuffer = pImageBuffer;
+ for (long i = 0; i < YEnd; i++)
+ {
+ if ( InternalReadLine( true, SkipC, XEnd, pLineBuffer ) ) return 1;
+ pLineBuffer += XEnd;
+ }
+
+ m_RegShadow[ Reg_Command ] &= !RegBit_FIFOCache; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ return 0;
+}
+
+
+
+// Returns 0 if successfull, 1 if Line_Done poll timed out.
+long CCameraIO::InternalReadLine( bool KeepData, long SkipC, long XEnd, unsigned short* pLineBuffer )
+{
+ struct apIOparam request;
+ int retval, status;
+
+ /////////////////////////////////////
+ // Clock out the line
+ m_RegShadow[ Reg_Command ] |= RegBit_StartNextLine; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= !RegBit_StartNextLine; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+
+ request.reg = RegISA_ImageData;
+ request.param1=(unsigned long)&retval;
+ request.param2=(int)m_PPRepeat;
+
+
+ for (long j = 0; j < SkipC; j++)
+ status=ioctl(fileHandle,APPPI_READ_USHORT,(unsigned long)&request);
+
+ if ( KeepData )
+ {
+ for (long j = 0; j < XEnd; j++) {
+ status=ioctl(fileHandle,APPPI_READ_USHORT,(unsigned long)&request);
+ *pLineBuffer++ = (unsigned short)retval;
+ }
+ }
+ else
+ {
+ for (long j = 0; j < XEnd; j++)
+ status=ioctl(fileHandle,APPPI_READ_USHORT,(unsigned long)&request);
+ }
+
+ /////////////////////////////////////
+ // Assert done reading line
+ m_RegShadow[ Reg_Command ] |= RegBit_DoneReading; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= !RegBit_DoneReading; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+
+ /////////////////////////////////////
+ // Wait until camera is done clocking
+ clock_t StopTime = clock() + CLOCKS_PER_SEC; // wait at most one second
+ while ( true )
+ {
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( ( val & RegBit_LineDone ) != 0 ) break;// Line done
+
+ clock_t CurrentTime = clock();
+ if ( CurrentTime > StopTime ) return 1; // Timed out
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/kstars/kstars/indi/apogee/CameraIO_PCI.cpp b/kstars/kstars/indi/apogee/CameraIO_PCI.cpp
new file mode 100644
index 00000000..3e6cc43e
--- /dev/null
+++ b/kstars/kstars/indi/apogee/CameraIO_PCI.cpp
@@ -0,0 +1,405 @@
+// CameraIO_PCI.cpp: implementation of the CCameraIO_PCI class.
+//
+// Copyright (c) 2000 Apogee Instruments Inc.
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include <winioctl.h>
+
+#include "ApogeeLinux.h" // This defines the IOCTL constants.
+#include "CameraIO_PCI.h"
+#include "time.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CCameraIO_PCI::CCameraIO_PCI()
+{
+ m_IsWDM = false;
+ m_hDriver = NULL;
+}
+
+CCameraIO_PCI::~CCameraIO_PCI()
+{
+ CloseDriver();
+}
+
+long CCameraIO_PCI::Read(unsigned short reg, unsigned short& val)
+{
+ BOOLEAN IoctlResult;
+ ULONG ReturnedLength;
+ USHORT RegNumber;
+ USHORT ReadBuffer;
+
+ switch ( reg )
+ {
+ case Reg_Command:
+ RegNumber = RegPCI_CommandRead;
+ break;
+ case Reg_Timer:
+ RegNumber = RegPCI_TimerRead;
+ break;
+ case Reg_VBinning:
+ RegNumber = RegPCI_VBinningRead;
+ break;
+ case Reg_AICCounter:
+ RegNumber = RegPCI_AICCounterRead;
+ break;
+ case Reg_TempSetPoint:
+ RegNumber = RegPCI_TempSetPointRead;
+ break;
+ case Reg_PixelCounter:
+ RegNumber = RegPCI_PixelCounterRead;
+ break;
+ case Reg_LineCounter:
+ RegNumber = RegPCI_LineCounterRead;
+ break;
+ case Reg_BICCounter:
+ RegNumber = RegPCI_BICCounterRead;
+ break;
+ case Reg_ImageData:
+ RegNumber = RegPCI_ImageData;
+ break;
+ case Reg_TempData:
+ RegNumber = RegPCI_TempData;
+ break;
+ case Reg_Status:
+ RegNumber = RegPCI_Status;
+ break;
+ case Reg_CommandReadback:
+ RegNumber = RegPCI_CommandReadback;
+ break;
+ default:
+ _ASSERT( FALSE ); // Application program bug
+ val = 0;
+ return 0;
+ }
+
+ if ( m_IsWDM )
+ {
+ IoctlResult = DeviceIoControl(
+ m_hDriver, // Handle to device
+ IOCTL_WDM_READ_PCI_USHORT, // IO Control code for Read
+ &RegNumber, // Buffer to driver.
+ sizeof(RegNumber), // Length of buffer in bytes.
+ &ReadBuffer, // Buffer from driver.
+ sizeof(ReadBuffer), // Length of buffer in bytes.
+ &ReturnedLength, // Bytes placed in DataBuffer.
+ NULL // NULL means wait till op. completes.
+ );
+ }
+ else
+ {
+ IoctlResult = DeviceIoControl(
+ m_hDriver, // Handle to device
+ IOCTL_GPD_READ_PCI_USHORT, // IO Control code for Read
+ &RegNumber, // Buffer to driver.
+ sizeof(RegNumber), // Length of buffer in bytes.
+ &ReadBuffer, // Buffer from driver.
+ sizeof(ReadBuffer), // Length of buffer in bytes.
+ &ReturnedLength, // Bytes placed in DataBuffer.
+ NULL // NULL means wait till op. completes.
+ );
+ }
+
+ if ( (ReturnedLength != 2) || (IoctlResult == FALSE) )
+ {
+ return 1;
+ }
+
+ val = ReadBuffer;
+
+ return 0;
+}
+
+long CCameraIO_PCI::Write(unsigned short reg, unsigned short val)
+{
+ BOOLEAN IoctlResult;
+ ULONG InBuffer[2];
+ ULONG ReturnedLength;
+ USHORT RegNumber;
+
+ switch ( reg )
+ {
+ case Reg_Command:
+ RegNumber = RegPCI_Command;
+ break;
+ case Reg_Timer:
+ RegNumber = RegPCI_Timer;
+ break;
+ case Reg_VBinning:
+ RegNumber = RegPCI_VBinning;
+ break;
+ case Reg_AICCounter:
+ RegNumber = RegPCI_AICCounter;
+ break;
+ case Reg_TempSetPoint:
+ RegNumber = RegPCI_TempSetPoint;
+ break;
+ case Reg_PixelCounter:
+ RegNumber = RegPCI_PixelCounter;
+ break;
+ case Reg_LineCounter:
+ RegNumber = RegPCI_LineCounter;
+ break;
+ case Reg_BICCounter:
+ RegNumber = RegPCI_BICCounter;
+ break;
+ default:
+ _ASSERT ( false );
+ return 0;
+ }
+
+ InBuffer[0] = RegNumber;
+ InBuffer[1] = val;
+
+ // Do an I/O write
+ if ( m_IsWDM )
+ {
+ IoctlResult = DeviceIoControl(
+ m_hDriver, // Handle to device
+ IOCTL_WDM_WRITE_PCI_USHORT, // IO Control code for Write
+ &InBuffer, // Buffer to driver. Holds register/data.
+ sizeof ( InBuffer ), // Length of buffer in bytes.
+ NULL, // Buffer from driver. Not used.
+ 0, // Length of buffer in bytes.
+ &ReturnedLength, // Bytes placed in outbuf. Should be 0.
+ NULL // NULL means wait till I/O completes.
+ );
+ }
+ else
+ {
+ IoctlResult = DeviceIoControl(
+ m_hDriver, // Handle to device
+ IOCTL_GPD_WRITE_PCI_USHORT, // IO Control code for Write
+ &InBuffer, // Buffer to driver. Holds register/data.
+ sizeof ( InBuffer ), // Length of buffer in bytes.
+ NULL, // Buffer from driver. Not used.
+ 0, // Length of buffer in bytes.
+ &ReturnedLength, // Bytes placed in outbuf. Should be 0.
+ NULL // NULL means wait till I/O completes.
+ );
+ }
+
+ if ( (IoctlResult == FALSE) || (ReturnedLength != 0) )
+ {
+ return 1;
+ }
+
+ return 0;
+
+}
+
+long CCameraIO_PCI::ReadLine( long SkipPixels, long Pixels, unsigned short* pLineBuffer )
+{
+ BOOLEAN IoctlResult;
+ ULONG InBuffer[3];
+ ULONG ReturnedLength; // Number of bytes returned in output buffer
+ ULONG NumBytes;
+ USHORT* DataBuffer;
+
+ InBuffer[0] = RegPCI_ImageData;
+ InBuffer[1] = SkipPixels; // Data points to skip
+ InBuffer[2] = Pixels; // Data points to keep
+
+ NumBytes = Pixels * sizeof( unsigned short );
+ DataBuffer = pLineBuffer;
+
+ if ( !m_TDI )
+ {
+ /////////////////////////////////////
+ // Clock out the line
+ m_RegShadow[ Reg_Command ] |= RegBit_StartNextLine; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_StartNextLine; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+ }
+
+ if ( m_IsWDM )
+ {
+ IoctlResult = DeviceIoControl(
+ m_hDriver, // Handle to device
+ IOCTL_WDM_READ_PCI_LINE, // IO Control code for Read line
+ &InBuffer, // Buffer to driver.
+ sizeof(InBuffer), // Length of buffer in bytes.
+ DataBuffer, // Buffer from driver.
+ NumBytes, // Length of buffer in bytes.
+ &ReturnedLength, // Bytes placed in DataBuffer.
+ NULL // NULL means wait till op. completes.
+ );
+ }
+ else
+ {
+ IoctlResult = DeviceIoControl(
+ m_hDriver, // Handle to device
+ IOCTL_GPD_READ_PCI_LINE, // IO Control code for Read line
+ &InBuffer, // Buffer to driver.
+ sizeof(InBuffer), // Length of buffer in bytes.
+ DataBuffer, // Buffer from driver.
+ NumBytes, // Length of buffer in bytes.
+ &ReturnedLength, // Bytes placed in DataBuffer.
+ NULL // NULL means wait till op. completes.
+ );
+ }
+
+ if ( (ReturnedLength != NumBytes) || (!IoctlResult) )
+ {
+ return 1; // Failed to get line info
+ }
+
+ /////////////////////////////////////
+ // Assert done reading line
+ m_RegShadow[ Reg_Command ] |= RegBit_DoneReading; // set bit to 1
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+
+ m_RegShadow[ Reg_Command ] &= ~RegBit_DoneReading; // set bit to 0
+ Write( Reg_Command, m_RegShadow[ Reg_Command ] );
+ /////////////////////////////////////
+
+ if ( !m_TDI )
+ {
+ /////////////////////////////////////
+ // Wait until camera is done
+ clock_t StopTime = clock() + CLOCKS_PER_SEC; // wait at most one second
+ while ( true )
+ {
+ unsigned short val = 0;
+ Read( Reg_Status, val );
+ if ( ( val & RegBit_LineDone ) != 0 ) break;// Line done
+
+ if ( clock() > StopTime ) return 1; // Timed out
+ }
+ }
+
+ return 0;
+}
+
+bool CCameraIO_PCI::InitDriver()
+{
+ OSVERSIONINFO OSVerInfo;
+ BOOLEAN IsPostWin98OS;
+ BOOLEAN IsNT4OS;
+ BOOLEAN IsPostNT4OS;
+
+ IsPostWin98OS = false;
+ IsNT4OS = false;
+ IsPostNT4OS = false;
+
+ CloseDriver();
+
+ OSVerInfo.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO );
+ GetVersionEx( &OSVerInfo );
+
+ // Check for Win9x versions. Pre-Win98 is unsupported.
+ if ( OSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
+ {
+ // Check for pre-Win98
+ if (( OSVerInfo.dwMajorVersion < 4 ) ||
+ (( OSVerInfo.dwMajorVersion == 4 ) && ( OSVerInfo.dwMinorVersion == 0 )))
+ {
+ return false; // Pre-Win98 not supported
+ }
+ else
+ {
+ IsPostWin98OS = true;
+ }
+
+ }
+ else if ( OSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
+ {
+ // Check if NT4
+ if ( OSVerInfo.dwMajorVersion < 4 )
+ {
+ // NT3.51 is not supported. Right??
+ return false;
+ }
+ else if (OSVerInfo.dwMajorVersion == 4 )
+ {
+ IsNT4OS = true;
+ }
+ else if (OSVerInfo.dwMajorVersion > 4 )
+ {
+ IsPostNT4OS = true;
+ }
+ }
+
+ if ( IsNT4OS )
+ {
+ ULONG ReturnedLength;
+ ULONG DataBuffer[2];
+
+ // Open the driver
+ m_hDriver = CreateFile(
+ "\\\\.\\ApogeeIO",
+ GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+
+ if ( m_hDriver == INVALID_HANDLE_VALUE )
+ {
+ m_hDriver = NULL;
+ return false;
+ }
+
+ BOOL IoctlResult = DeviceIoControl(
+ m_hDriver, // Handle to device
+ IOCTL_PCI_BUS_SCAN, // IO Control code for PCI Bus Scan
+ NULL, // Buffer to driver.
+ 0, // Length of buffer in bytes.
+ DataBuffer, // Buffer from driver.
+ sizeof( DataBuffer ), // Length of buffer in bytes.
+ &ReturnedLength, // Bytes placed in DataBuffer.
+ NULL // NULL means wait till op. completes.
+ );
+
+ if ( (!IoctlResult) || (ReturnedLength != sizeof(DataBuffer)) )
+ {
+ return false;
+ }
+ }
+ else if ( IsPostWin98OS || IsPostNT4OS )
+ {
+ // Should be okay to use the WDM driver. Note that the kernel
+ // driver will actually check to see if WDM services are available
+
+ // Open the driver
+ m_hDriver = CreateFile(
+ "\\\\.\\ApPCI",
+ GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+
+ if ( m_hDriver == INVALID_HANDLE_VALUE )
+ {
+ m_hDriver = NULL;
+ return false;
+ }
+
+ // Safe to assume we're using the WDM driver at this point.
+ m_IsWDM = true;
+ }
+
+ return true;
+}
+
+void CCameraIO_PCI::CloseDriver()
+{
+ // Close the driver if it already exists
+ if ( m_hDriver != NULL )
+ {
+ CloseHandle ( m_hDriver );
+ }
+
+ m_hDriver = NULL;
+}
diff --git a/kstars/kstars/indi/apogee/CameraIO_PCI.h b/kstars/kstars/indi/apogee/CameraIO_PCI.h
new file mode 100644
index 00000000..c1b4adf4
--- /dev/null
+++ b/kstars/kstars/indi/apogee/CameraIO_PCI.h
@@ -0,0 +1,35 @@
+// CameraIO_PCI.h: interface for the CCameraIO_PCI class.
+//
+// Copyright (c) 2000 Apogee Instruments Inc.
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CAMERAIO_PCI_H__0F583058_8596_11D4_915F_0060676644C1__INCLUDED_)
+#define AFX_CAMERAIO_PCI_H__0F583058_8596_11D4_915F_0060676644C1__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "CameraIO.h"
+
+class CCameraIO_PCI : public CCameraIO
+{
+public:
+
+ CCameraIO_PCI();
+ virtual ~CCameraIO_PCI();
+
+ bool InitDriver();
+ long ReadLine( long SkipPixels, long Pixels, unsigned short* pLineBuffer );
+ long Write( unsigned short reg, unsigned short val );
+ long Read( unsigned short reg, unsigned short& val );
+
+private:
+
+ BOOLEAN m_IsWDM;
+ HANDLE m_hDriver;
+
+ void CloseDriver();
+};
+
+#endif // !defined(AFX_CAMERAIO_PCI_H__0F583058_8596_11D4_915F_0060676644C1__INCLUDED_)
diff --git a/kstars/kstars/indi/apogee/Camera_Example.cpp b/kstars/kstars/indi/apogee/Camera_Example.cpp
new file mode 100644
index 00000000..f1f64121
--- /dev/null
+++ b/kstars/kstars/indi/apogee/Camera_Example.cpp
@@ -0,0 +1,631 @@
+// Example source code for implementing the CCameraIO object
+
+#include "windows.h"
+#include "stdio.h"
+
+#include "CameraIO.h"
+#include "CameraIO_ISA_9x.h"
+#include "CameraIO_PPI_9x.h"
+
+#include "CameraIO_ISA_NT.h"
+#include "CameraIO_PPI_NT.h"
+
+#include "CameraIO_PCI.h"
+
+
+// Error codes returned from config_load
+const long CCD_OPEN_NOERR = 0; // No error detected
+const long CCD_OPEN_CFGNAME = 1; // No config file specified
+const long CCD_OPEN_CFGDATA = 2; // Config missing or missing required data
+const long CCD_OPEN_LOOPTST = 3; // Loopback test failed, no camera found
+const long CCD_OPEN_ALLOC = 4; // Memory alloc failed - system error
+const long CCD_OPEN_NTIO = 5; // NT I/O driver not present
+
+CCameraIO* cam; // the Camera interface object
+
+// Function declarations for this file
+int InitCam( char* cfgname );
+long config_load( char* cfgname, short BaseAddress, short RegOffset );
+bool CfgGet ( FILE* inifp,
+ char* inisect,
+ char* iniparm,
+ char* retbuff,
+ short bufflen,
+ short* parmlen);
+
+unsigned short hextoi(char* instr);
+void trimstr(char* s);
+
+// Initializes the CameraIO object from an INI file specified by cfgname
+int InitCam( char* cfgname )
+{
+ long ret = config_load( cfgname, -1, -1 );
+ if ( ret == 0 )
+ {
+ // We can now access the cam objects members
+ cam->Flush(); // Start the camera flushing
+ return 0;
+ }
+ else
+ {
+ switch ( ret )
+ {
+ case CCD_OPEN_CFGNAME:
+ // "No config file specified."
+ break;
+ case CCD_OPEN_CFGDATA:
+ // "Config file missing or missing required data."
+ break;
+ case CCD_OPEN_LOOPTST:
+ // "Loopback test failed, no camera found"
+ break;
+ case CCD_OPEN_ALLOC:
+ // "Memory allocation failed - system error"
+ break;
+ case CCD_OPEN_NTIO:
+ // "NT I/O driver not present"
+ break;
+ }
+ return ret;
+ }
+}
+
+// Convert a string to a decimal or hexadecimal integer
+unsigned short hextoi(char *instr)
+{
+ unsigned short val, tot = 0;
+ bool IsHEX = false;
+
+ long n = strlen( instr );
+ if ( n > 1 )
+ { // Look for hex format e.g. 8Fh, A3H or 0x5D
+ if ( instr[ n - 1 ] == 'h' || instr[ n - 1 ] == 'H' )
+ IsHEX = true;
+ else if ( *instr == '0' && *(instr+1) == 'x' )
+ {
+ IsHEX = true;
+ instr += 2;
+ }
+ }
+
+ if ( IsHEX )
+ {
+ while (instr && *instr && isxdigit(*instr))
+ {
+ val = *instr++ - '0';
+ if (9 < val)
+ val -= 7;
+ tot <<= 4;
+ tot |= (val & 0x0f);
+ }
+ }
+ else
+ tot = atoi( instr );
+
+ return tot;
+}
+
+// Trim trailing spaces from a string
+void trimstr(char *s)
+{
+ char *p;
+
+ p = s + (strlen(s) - 1);
+ while (isspace(*p))
+ p--;
+ *(++p) = '\0';
+}
+
+
+//-------------------------------------------------------------
+// CfgGet
+//
+// Retrieve a parameter from an INI file. Returns a status code
+// and the paramter string in retbuff.
+//-------------------------------------------------------------
+bool CfgGet ( FILE* inifp,
+ char *inisect,
+ char *iniparm,
+ char *retbuff,
+ short bufflen,
+ short *parmlen)
+{
+ short gotsect;
+ char tbuf[256];
+ char *ss, *eq, *ps, *vs, *ptr;
+
+ rewind( inifp );
+
+ // find the target section
+
+ gotsect = 0;
+ while (fgets(tbuf,256,inifp) != NULL) {
+ if ((ss = strchr(tbuf,'[')) != NULL) {
+ if (strnicmp(ss+1,inisect,strlen(inisect)) == 0) {
+ gotsect = 1;
+ break;
+ }
+ }
+ }
+
+ if (!gotsect) { // section not found
+ return false;
+ }
+
+ while (fgets(tbuf,256,inifp) != NULL) { // find parameter in sect
+
+ if ((ptr = strrchr(tbuf,'\n')) != NULL) // remove newline if there
+ *ptr = '\0';
+
+ ps = tbuf+strspn(tbuf," \t"); // find the first non-blank
+
+ if (*ps == ';') // Skip line if comment
+ continue;
+
+ if (*ps == '[') { // Start of next section
+ return false;
+ }
+
+ eq = strchr(ps,'='); // Find '=' sign in string
+
+ if (eq)
+ vs = eq + 1 + strspn(eq+1," \t"); // Find start of value str
+ else
+ continue;
+
+ // found the target parameter
+
+ if (strnicmp(ps,iniparm,strlen(iniparm)) == 0) {
+
+ if ((ptr = strchr(vs,';')) != NULL) // cut off an EOL comment
+ *ptr = '\0';
+
+ if (short(strlen(vs)) > bufflen - 1) {// not enough buffer space
+ strncpy(retbuff,vs,bufflen - 1);
+ retbuff[bufflen - 1] = '\0'; // put EOL in string
+ *parmlen = bufflen;
+ return true;
+ }
+ else {
+ strcpy(retbuff,vs); // got it
+ trimstr(retbuff); // trim any trailing blanks
+ *parmlen = strlen(retbuff);
+ return true;
+ }
+ }
+ }
+
+ return false; // parameter not found
+}
+
+// Initializes internal variables to their default value and reads the parameters in the
+// specified INI file. Then initializes the camera using current settings. If BaseAddress
+// or RegOffset parameters are specified (not equal to -1) then one or both of these
+// values are used for the m_BaseAddress and m_RegisterOffset properties overriding those
+// settings in the INI file.
+long config_load( char* cfgname, short BaseAddress, short RegOffset )
+{
+ short plen;
+ char retbuf[256];
+
+ if ((strlen(cfgname) == 0) || (cfgname[0] == '\0')) return CCD_OPEN_CFGNAME;
+
+ // attempt to open INI file
+ FILE* inifp = NULL;
+
+ if ((inifp = fopen(cfgname,"r")) == NULL) return CCD_OPEN_CFGDATA;
+
+ // Check whether we are on an NT platform
+ OSVERSIONINFO VersionInfo;
+ memset(&VersionInfo, 0, sizeof(OSVERSIONINFO));
+ VersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+ GetVersionEx ( &VersionInfo );
+ bool IsNT = VersionInfo.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS;
+
+ // System
+ if (CfgGet (inifp, "system", "interface", retbuf, sizeof(retbuf), &plen))
+ {
+ // Assume cam is currently null
+ if ( stricmp( "isa", retbuf ) == 0 )
+ {
+ if ( IsNT )
+ cam = new CCameraIO_ISA_NT;
+ else
+ cam = new CCameraIO_ISA_9x;
+ }
+ else if ( stricmp( "ppi", retbuf ) == 0 )
+ {
+ if ( IsNT )
+ cam = new CCameraIO_PPI_NT;
+ else
+ cam = new CCameraIO_PPI_9x;
+ }
+ else if ( stricmp( "pci", retbuf ) == 0 )
+ {
+ cam = new CCameraIO_PCI;
+ }
+
+ if ( cam == NULL )
+ {
+ fclose( inifp );
+ return CCD_OPEN_ALLOC;
+ }
+ }
+ else
+ {
+ fclose( inifp );
+ return CCD_OPEN_CFGDATA;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Settings which are stored in a class member (not in firmware) are already set
+ // to a default value in the constructor. Settings accessed by get/put functions
+ // must be set to a default value in this routine, after the base address and
+ // communication protocal is setup.
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // These settings must done first since they affect communication with the camera
+
+ if ( BaseAddress == -1 )
+ {
+ if (CfgGet (inifp, "system", "base", retbuf, sizeof(retbuf), &plen))
+ cam->m_BaseAddress = hextoi(retbuf) & 0xFFF;
+ else
+ {
+ fclose( inifp );
+ delete cam;
+ cam = NULL;
+ return CCD_OPEN_CFGDATA; // base address MUST be defined
+ }
+ }
+ else
+ cam->m_BaseAddress = BaseAddress & 0xFFF;
+
+ if ( RegOffset == -1 )
+ {
+ if (CfgGet (inifp, "system", "reg_offset", retbuf, sizeof(retbuf), &plen))
+ {
+ unsigned short val = hextoi(retbuf);
+ if ( val >= 0x0 && val <= 0xF0 ) cam->m_RegisterOffset = val & 0xF0;
+ }
+ }
+ else
+ {
+ if ( RegOffset >= 0x0 && RegOffset <= 0xF0 ) cam->m_RegisterOffset = RegOffset & 0xF0;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Necessary geometry settings
+
+ if (CfgGet (inifp, "geometry", "rows", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 1 && val <= MAXTOTALROWS ) cam->m_Rows = val;
+ }
+ else
+ {
+ fclose( inifp );
+ delete cam;
+ cam = NULL;
+ return CCD_OPEN_CFGDATA; // rows MUST be defined
+ }
+
+ if (CfgGet (inifp, "geometry", "columns", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 1 && val <= MAXTOTALCOLUMNS ) cam->m_Columns = val;
+ }
+ else
+ {
+ fclose( inifp );
+ delete cam;
+ cam = NULL;
+ return CCD_OPEN_CFGDATA; // columns MUST be defined
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+
+ if (CfgGet (inifp, "system", "pp_repeat", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi( retbuf );
+ if ( val > 0 && val <= 1000 ) cam->m_PPRepeat = val;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // First actual communication with camera if in PPI mode
+ if ( !cam->InitDriver() )
+ {
+ delete cam;
+ cam = NULL;
+ fclose( inifp );
+ if ( IsNT )
+ return CCD_OPEN_NTIO;
+ else
+ return CCD_OPEN_LOOPTST;
+ }
+ /////////////////////////////////////////////////////////////////////////////////
+ // First actual communication with camera if in ISA mode
+ cam->Reset(); // Read in command register to set shadow register known state
+ /////////////////////////////////////////////////////////////////////////////////
+
+ if (CfgGet (inifp, "system", "cable", retbuf, sizeof(retbuf), &plen))
+ {
+ if (!stricmp("LONG",retbuf))
+ cam->write_LongCable( true );
+ else if ( !stricmp("SHORT",retbuf) )
+ cam->write_LongCable( false );
+ }
+ else
+ cam->write_LongCable( false ); // default
+
+ if ( !cam->read_Present() )
+ {
+ delete cam;
+ cam = NULL;
+ fclose( inifp );
+
+ return CCD_OPEN_LOOPTST;
+ }
+ /////////////////////////////////////////////////////////////////////////////////
+ // Set default setting and read other settings from ini file
+
+ cam->write_UseTrigger( false );
+ cam->write_ForceShutterOpen( false );
+
+ if (CfgGet (inifp, "system", "high_priority", retbuf, sizeof(retbuf), &plen))
+ {
+ if (!stricmp("ON",retbuf) || !stricmp("TRUE",retbuf) || !stricmp("1",retbuf))
+ {
+ cam->m_HighPriority = true;
+ }
+ else if (!stricmp("OFF",retbuf) || !stricmp("FALSE",retbuf) || !stricmp("0",retbuf))
+ {
+ cam->m_HighPriority = false;
+ }
+ }
+
+ if (CfgGet (inifp, "system", "data_bits", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi( retbuf );
+ if ( val >= 8 && val <= 18 ) cam->m_DataBits = val;
+ }
+
+ if (CfgGet (inifp, "system", "sensor", retbuf, sizeof(retbuf), &plen))
+ {
+ if ( stricmp( "ccd", retbuf ) == 0 )
+ {
+ cam->m_SensorType = Camera_SensorType_CCD;
+ }
+ else if ( stricmp( "cmos", retbuf ) == 0 )
+ {
+ cam->m_SensorType = Camera_SensorType_CMOS;
+ }
+ }
+
+ if (CfgGet (inifp, "system", "mode", retbuf, sizeof(retbuf), &plen))
+ {
+ unsigned short val = hextoi(retbuf) & 0xF;
+ cam->write_Mode( val );
+ }
+ else
+ cam->write_Mode( 0 ); // default
+
+ if (CfgGet (inifp, "system", "test", retbuf, sizeof(retbuf), &plen))
+ {
+ unsigned short val = hextoi(retbuf) & 0xF;
+ cam->write_TestBits( val );
+ }
+ else
+ cam->write_TestBits( 0 ); //default
+
+ if (CfgGet (inifp, "system", "test2", retbuf, sizeof(retbuf), &plen))
+ {
+ unsigned short val = hextoi(retbuf) & 0xF;
+ cam->write_Test2Bits( val );
+ }
+ else
+ cam->write_Test2Bits( 0 ); // default
+
+ cam->write_FastReadout( false ); //default
+
+ if (CfgGet (inifp, "system", "shutter_speed", retbuf, sizeof(retbuf), &plen))
+ {
+ if (!stricmp("normal",retbuf))
+ {
+ cam->m_FastShutter = false;
+ cam->m_MaxExposure = 10485.75;
+ cam->m_MinExposure = 0.01;
+ }
+ else if (!stricmp("fast",retbuf))
+ {
+ cam->m_FastShutter = true;
+ cam->m_MaxExposure = 1048.575;
+ cam->m_MinExposure = 0.001;
+ }
+ else if ( !stricmp("dual",retbuf))
+ {
+ cam->m_FastShutter = true;
+ cam->m_MaxExposure = 10485.75;
+ cam->m_MinExposure = 0.001;
+ }
+ }
+
+ if (CfgGet (inifp, "system", "shutter_bits", retbuf, sizeof(retbuf), &plen))
+ {
+ unsigned short val = hextoi(retbuf);
+ cam->m_FastShutterBits_Mode = val & 0x0F;
+ cam->m_FastShutterBits_Test = ( val & 0xF0 ) >> 4;
+ }
+
+ if (CfgGet (inifp, "system", "maxbinx", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 1 && val <= MAXHBIN ) cam->m_MaxBinX = val;
+ }
+
+ if (CfgGet (inifp, "system", "maxbiny", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 1 && val <= MAXVBIN ) cam->m_MaxBinY = val;
+ }
+
+ if (CfgGet (inifp, "system", "guider_relays", retbuf, sizeof(retbuf), &plen))
+ {
+ if (!stricmp("ON",retbuf) || !stricmp("TRUE",retbuf) || !stricmp("1",retbuf))
+ {
+ cam->m_GuiderRelays = true;
+ }
+ else if (!stricmp("OFF",retbuf) || !stricmp("FALSE",retbuf) || !stricmp("0",retbuf))
+ {
+ cam->m_GuiderRelays = false;
+ }
+ }
+
+ if (CfgGet (inifp, "system", "timeout", retbuf, sizeof(retbuf), &plen))
+ {
+ double val = atof(retbuf);
+ if ( val >= 0.0 && val <= 10000.0 ) cam->m_Timeout = val;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Geometry
+
+ if (CfgGet (inifp, "geometry", "bic", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 1 && val <= MAXCOLUMNS ) cam->m_BIC = val;
+ }
+
+ if (CfgGet (inifp, "geometry", "bir", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 1 && val <= MAXROWS ) cam->m_BIR = val;
+ }
+
+ if (CfgGet (inifp, "geometry", "skipc", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 0 && val <= MAXCOLUMNS ) cam->m_SkipC = val;
+ }
+
+ if (CfgGet (inifp, "geometry", "skipr", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 0 && val <= MAXROWS ) cam->m_SkipR = val;
+ }
+
+ if (CfgGet (inifp, "geometry", "imgcols", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 1 && val <= MAXTOTALCOLUMNS ) cam->m_ImgColumns = val;
+ }
+ else
+ cam->m_ImgColumns = cam->m_Columns - cam->m_BIC - cam->m_SkipC;
+
+ if (CfgGet (inifp, "geometry", "imgrows", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 1 && val <= MAXTOTALROWS ) cam->m_ImgRows = val;
+ }
+ else
+ cam->m_ImgRows = cam->m_Rows - cam->m_BIR - cam->m_SkipR;
+
+ if (CfgGet (inifp, "geometry", "hflush", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 1 && val <= MAXHBIN ) cam->m_HFlush = val;
+ }
+
+ if (CfgGet (inifp, "geometry", "vflush", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 1 && val <= MAXVBIN ) cam->m_VFlush = val;
+ }
+
+ // Default to full frame
+ cam->m_NumX = cam->m_ImgColumns;
+ cam->m_NumY = cam->m_ImgRows;
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // Temperature
+
+ if (CfgGet (inifp, "temp", "control", retbuf, sizeof(retbuf), &plen))
+ {
+ if (!stricmp("ON",retbuf) || !stricmp("TRUE",retbuf) || !stricmp("1",retbuf))
+ {
+ cam->m_TempControl = true;
+ }
+ else if (!stricmp("OFF",retbuf) || !stricmp("FALSE",retbuf) || !stricmp("0",retbuf))
+ {
+ cam->m_TempControl = false;
+ }
+ }
+
+ if (CfgGet (inifp, "temp", "cal", retbuf, sizeof(retbuf), &plen))
+ {
+ short val = hextoi(retbuf);
+ if ( val >= 1 && val <= 255 ) cam->m_TempCalibration = val;
+ }
+
+ if (CfgGet (inifp, "temp", "scale", retbuf, sizeof(retbuf), &plen))
+ {
+ double val = atof(retbuf);
+ if ( val >= 1.0 && val <= 10.0 ) cam->m_TempScale = val;
+ }
+
+ if (CfgGet (inifp, "temp", "target", retbuf, sizeof(retbuf), &plen))
+ {
+ double val = atof(retbuf);
+ if ( val >= -60.0 && val <= 40.0 )
+ cam->write_CoolerSetPoint( val );
+ else
+ cam->write_CoolerSetPoint( -10.0 );
+ }
+ else
+ cam->write_CoolerSetPoint( -10.0 ); //default
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // CCD
+
+ if (CfgGet (inifp, "ccd", "sensor", retbuf, sizeof(retbuf), &plen))
+ {
+ if ( plen > 256 ) plen = 256;
+ memcpy( cam->m_Sensor, retbuf, plen );
+ }
+
+ if (CfgGet (inifp, "ccd", "color", retbuf, sizeof(retbuf), &plen))
+ {
+ if (!stricmp("ON",retbuf) || !stricmp("TRUE",retbuf) || !stricmp("1",retbuf))
+ {
+ cam->m_Color = true;
+ }
+ else if (!stricmp("OFF",retbuf) || !stricmp("FALSE",retbuf) || !stricmp("0",retbuf))
+ {
+ cam->m_Color = false;
+ }
+ }
+
+ if (CfgGet (inifp, "ccd", "noise", retbuf, sizeof(retbuf), &plen))
+ {
+ cam->m_Noise = atof( retbuf );
+ }
+
+ if (CfgGet (inifp, "ccd", "gain", retbuf, sizeof(retbuf), &plen))
+ {
+ cam->m_Gain = atof( retbuf );
+ }
+
+ if (CfgGet (inifp, "ccd", "pixelxsize", retbuf, sizeof(retbuf), &plen))
+ {
+ cam->m_PixelXSize = atof( retbuf );
+ }
+
+ if (CfgGet (inifp, "ccd", "pixelysize", retbuf, sizeof(retbuf), &plen))
+ {
+ cam->m_PixelYSize = atof( retbuf );
+ }
+
+ fclose( inifp );
+ return CCD_OPEN_NOERR;
+}
+
diff --git a/kstars/kstars/indi/apogee/FpgaRegs.h b/kstars/kstars/indi/apogee/FpgaRegs.h
new file mode 100644
index 00000000..b1fd5fe1
--- /dev/null
+++ b/kstars/kstars/indi/apogee/FpgaRegs.h
@@ -0,0 +1,190 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __FPGAREGS_H__APOGEE_APN__
+#define __FPGAREGS_H__APOGEE_APN__
+
+
+#define FPGA_TOTAL_REGISTER_COUNT 103
+
+
+#define FPGA_REG_COMMAND_A 0
+#define FPGA_BIT_CMD_EXPOSE 0x0001
+#define FPGA_BIT_CMD_DARK 0x0002
+#define FPGA_BIT_CMD_TEST 0x0004
+#define FPGA_BIT_CMD_TDI 0x0008
+#define FPGA_BIT_CMD_FLUSH 0x0010
+#define FPGA_BIT_CMD_TRIGGER_EXPOSE 0x0020
+
+#define FPGA_REG_COMMAND_B 1
+#define FPGA_BIT_CMD_RESET 0x0002
+#define FPGA_BIT_CMD_CLEAR_ALL 0x0010
+#define FPGA_BIT_CMD_END_EXPOSURE 0x0080
+#define FPGA_BIT_CMD_RAMP_TO_SETPOINT 0x0200
+#define FPGA_BIT_CMD_RAMP_TO_AMBIENT 0x0400
+#define FPGA_BIT_CMD_START_TEMP_READ 0x2000
+#define FPGA_BIT_CMD_DAC_LOAD 0x4000
+#define FPGA_BIT_CMD_AD_CONFIG 0x8000
+
+#define FPGA_REG_OP_A 2
+#define FPGA_BIT_LED_DISABLE 0x0001
+#define FPGA_BIT_PAUSE_TIMER 0x0002
+#define FPGA_BIT_RATIO 0x0004
+#define FPGA_BIT_DELAY_MODE 0x0008
+#define FPGA_BIT_P_CLK_MODE 0x0010
+#define FPGA_BIT_LED_EXPOSE_DISABLE 0x0020
+#define FPGA_BIT_DISABLE_H_CLK 0x0040
+#define FPGA_BIT_SHUTTER_AMP_CONTROL 0x0080
+#define FPGA_BIT_HALT_DISABLE 0x0100
+#define FPGA_BIT_SHUTTER_MODE 0x0200
+#define FPGA_BIT_DIGITIZATION_RES 0x0400
+#define FPGA_BIT_FORCE_SHUTTER 0x0800
+#define FPGA_BIT_DISABLE_SHUTTER 0x1000
+#define FPGA_BIT_TEMP_SUSPEND 0x2000
+#define FPGA_BIT_SHUTTER_SOURCE 0x4000
+#define FPGA_BIT_TEST_MODE 0x8000
+
+#define FPGA_REG_OP_B 3
+#define FPGA_BIT_HCLAMP_ENABLE 0x0008
+#define FPGA_BIT_HSKIP_ENABLE 0x0010
+#define FPGA_BIT_HRAM_ENABLE 0x0020
+#define FPGA_BIT_VRAM_ENABLE 0x0040
+#define FPGA_BIT_DAC_SELECT_ZERO 0x0080
+#define FPGA_BIT_DAC_SELECT_ONE 0x0100
+#define FPGA_BIT_AD_SIMULATION 0x8000
+
+#define FPGA_REG_TIMER_UPPER 4
+#define FPGA_REG_TIMER_LOWER 5
+
+#define FPGA_REG_HRAM_INPUT 6
+#define FPGA_REG_VRAM_INPUT 7
+
+#define FPGA_REG_HRAM_INV_MASK 8
+#define FPGA_REG_VRAM_INV_MASK 9
+
+#define FPGA_REG_HCLAMP_INPUT 10
+#define FPGA_REG_HSKIP_INPUT 11
+
+#define FPGA_REG_PRECLAMP_SKIP_COUNT 12
+#define FPGA_REG_CLAMP_COUNT 13
+#define FPGA_REG_PREROI_SKIP_COUNT 14
+#define FPGA_REG_ROI_COUNT 15
+#define FPGA_REG_POSTROI_SKIP_COUNT 16
+#define FPGA_REG_OVERSCAN_COUNT 17
+#define FPGA_REG_IMAGE_COUNT 18
+
+#define FPGA_REG_VFLUSH_BINNING 19
+
+#define FPGA_REG_SHUTTER_CLOSE_DELAY 20
+
+#define FPGA_REG_POSTOVERSCAN_SKIP_COUNT 21
+
+#define FPGA_REG_SHUTTER_STROBE_POSITION 23
+#define FPGA_REG_SHUTTER_STROBE_PERIOD 24
+
+#define FPGA_REG_FAN_SPEED_CONTROL 25
+#define FPGA_REG_LED_DRIVE 26
+#define FPGA_REG_SUBSTRATE_ADJUST 27
+#define FPGA_MASK_FAN_SPEED_CONTROL 0x0FFF
+#define FPGA_MASK_LED_ILLUMINATION 0x0FFF
+#define FPGA_MASK_SUBSTRATE_ADJUST 0x0FFF
+
+#define FPGA_REG_TEST_COUNT_UPPER 28
+#define FPGA_REG_TEST_COUNT_LOWER 29
+
+#define FPGA_REG_A1_ROW_COUNT 30
+#define FPGA_REG_A1_VBINNING 31
+#define FPGA_REG_A2_ROW_COUNT 32
+#define FPGA_REG_A2_VBINNING 33
+#define FPGA_REG_A3_ROW_COUNT 34
+#define FPGA_REG_A3_VBINNING 35
+
+#define FPGA_MASK_VBINNING 0x0FFF
+#define FPGA_BIT_ARRAY_DIGITIZE 0x1000
+#define FPGA_BIT_ARRAY_FASTDUMP 0x4000
+
+#define FPGA_REG_SEQUENCE_DELAY 47
+#define FPGA_REG_TDI_RATE 48
+
+#define FPGA_REG_IO_PORT_WRITE 49
+
+#define FPGA_REG_IO_PORT_DIRECTION 50
+#define FPGA_MASK_IO_PORT_DIRECTION 0x003F
+
+#define FPGA_REG_IO_PORT_ASSIGNMENT 51
+#define FPGA_MASK_IO_PORT_ASSIGNMENT 0x003F
+
+#define FPGA_REG_LED_SELECT 52
+#define FPGA_MASK_LED_SELECT_A 0x000F
+#define FPGA_MASK_LED_SELECT_B 0x00F0
+#define FPGA_BIT_LED_EXPOSE 0x0001
+#define FPGA_BIT_LED_IMAGE_ACTIVE 0x0002
+#define FPGA_BIT_LED_FLUSHING 0x0004
+#define FPGA_BIT_LED_TRIGGER_WAIT 0x0008
+#define FPGA_BIT_LED_EXT_TRIGGER 0x0010
+#define FPGA_BIT_LED_EXT_SHUTTER_INPUT 0x0020
+#define FPGA_BIT_LED_EXT_START_READOUT 0x0040
+#define FPGA_BIT_LED_AT_TEMP 0x0080
+
+#define FPGA_REG_SCRATCH 53
+
+#define FPGA_REG_TDI_COUNT 54
+
+#define FPGA_REG_TEMP_DESIRED 55
+
+#define FPGA_REG_TEMP_RAMP_DOWN_A 57
+#define FPGA_REG_TEMP_RAMP_DOWN_B 58
+#define FPGA_REG_TEMP_BACKOFF 60
+#define FPGA_REG_TEMP_COOLER_OVERRIDE 61
+#define FPGA_MASK_TEMP_PARAMS 0x0FFF // 12 bits
+
+#define FPGA_REG_AD_CONFIG_DATA 62
+#define FPGA_MASK_AD_GAIN 0x07FF // 11 bits
+
+#define FPGA_REG_IO_PORT_READ 90
+#define FPGA_MASK_IO_PORT_DATA 0x003F
+
+#define FPGA_REG_GENERAL_STATUS 91
+#define FPGA_BIT_STATUS_IMAGE_EXPOSING 0x0001
+#define FPGA_BIT_STATUS_IMAGING_ACTIVE 0x0002
+#define FPGA_BIT_STATUS_DATA_HALTED 0x0004
+#define FPGA_BIT_STATUS_IMAGE_DONE 0x0008
+#define FPGA_BIT_STATUS_FLUSHING 0x0010
+#define FPGA_BIT_STATUS_WAITING_TRIGGER 0x0020
+#define FPGA_BIT_STATUS_SHUTTER_OPEN 0x0040
+#define FPGA_BIT_STATUS_PATTERN_ERROR 0x0080
+#define FPGA_BIT_STATUS_TEMP_SUSPEND_ACK 0x0100
+#define FPGA_BIT_STATUS_TEMP_REVISION 0x2000
+#define FPGA_BIT_STATUS_TEMP_AT_TEMP 0x4000
+#define FPGA_BIT_STATUS_TEMP_ACTIVE 0x8000
+
+#define FPGA_REG_TEMP_HEATSINK 93
+#define FPGA_REG_TEMP_CCD 94
+#define FPGA_REG_TEMP_DRIVE 95
+
+#define FPGA_REG_INPUT_VOLTAGE 96
+#define FPGA_MASK_INPUT_VOLTAGE 0x0FFF
+
+#define FPGA_REG_TEMP_REVISED 97
+
+#define FPGA_REG_FIFO_DATA 98
+#define FPGA_REG_FIFO_STATUS 99
+
+#define FPGA_REG_CAMERA_ID 100
+#define FPGA_MASK_CAMERA_ID 0x007F
+
+#define FPGA_REG_FIRMWARE_REV 101
+
+#define FPGA_REG_FIFO_FULL_COUNT 102
+#define FPGA_REG_FIFO_EMPTY_COUNT 103
+
+#define FPGA_REG_TDI_COUNTER 104
+#define FPGA_REG_SEQUENCE_COUNTER 105
+
+#endif
diff --git a/kstars/kstars/indi/apogee/Makefile.am b/kstars/kstars/indi/apogee/Makefile.am
new file mode 100644
index 00000000..3d62dadc
--- /dev/null
+++ b/kstars/kstars/indi/apogee/Makefile.am
@@ -0,0 +1,22 @@
+INCLUDES =
+METASOURCES = AUTO
+
+if HAVE_LIBUSB
+libapogee_target = libapogee_USB.la
+endif
+
+if LINUX
+apogee_targets = libapogee_ISA.la libapogee_PCI.la libapogee_PPI.la $(libapogee_target)
+endif
+
+noinst_LTLIBRARIES = $(apogee_targets)
+
+libapogee_ISA_la_SOURCES = CameraIO_Linux.cpp CameraIO_LinuxISA.cpp
+libapogee_PCI_la_SOURCES = CameraIO_Linux.cpp CameraIO_LinuxPCI.cpp
+libapogee_PPI_la_SOURCES = CameraIO_Linux.cpp CameraIO_LinuxPPI.cpp
+
+libapogee_USB_la_SOURCES = ApnCamData.cpp ApnCamData_CCD3011HS.cpp ApnCamData_CCD3011LS.cpp ApnCamData_CCD4240HS.cpp ApnCamData_CCD4240LS.cpp ApnCamData_CCD4710HS.cpp ApnCamData_CCD4710LS.cpp ApnCamData_CCD4710LS2.cpp ApnCamData_CCD4710LS3.cpp ApnCamData_CCD4710LS4.cpp ApnCamData_CCD4710LS5.cpp ApnCamData_CCD4720HS.cpp ApnCamData_CCD4720LS.cpp ApnCamData_CCD5520HS.cpp ApnCamData_CCD5520LS.cpp ApnCamData_CCD5710HS.cpp ApnCamData_CCD5710LS.cpp ApnCamData_CCD7700HS.cpp ApnCamData_CCD7700LS.cpp ApnCamData_KAF0261E.cpp ApnCamData_KAF0401E.cpp ApnCamData_KAF1001E.cpp ApnCamData_KAF1301E.cpp ApnCamData_KAF1401E.cpp ApnCamData_KAF3200E.cpp ApnCamData_KAF4202.cpp ApnCamData_KAF1602E.cpp ApnCamData_KAF16801E.cpp ApnCamData_KAF6303E.cpp ApnCamData_TH7899.cpp ApnCamTable.cpp ApnCamera.cpp ApnCamera_USB.cpp ApnCamera_Linux.cpp ApogeeUsbLinux.cpp
+libapogee_USB_la_LADD = -lusb
+
+KDE_OPTIONS = nofinal
+KDE_CXXFLAGS = -D_POSIX_C_SOURCE=199506L
diff --git a/kstars/kstars/indi/apogee/reb1100.cpp b/kstars/kstars/indi/apogee/reb1100.cpp
new file mode 100644
index 00000000..cacf16eb
--- /dev/null
+++ b/kstars/kstars/indi/apogee/reb1100.cpp
@@ -0,0 +1,195 @@
+/***************************************************************************
+ reb1100.cpp - REB1100 communication class
+ -------------------
+ begin : Thu Mar 27 2003
+ copyright : (C) 2003 by Igor Izyumin
+ email : igor@mlug.missouri.edu
+ ***************************************************************************/
+
+/***************************************************************************
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
+
+ **********************************************************************/
+
+#include "reb1100.h"
+
+REB1100::REB1100(){
+ struct usb_bus *bus;
+ struct usb_device *dev;
+
+ usb_init();
+
+ usb_find_busses();
+ usb_find_devices();
+
+ char string[256];
+
+ int found = 0;
+
+ /* find ebook device */
+ for(bus = usb_busses; bus && !found; bus = bus->next) {
+ for(dev = bus->devices; dev && !found; dev = dev->next) {
+ if (dev->descriptor.idVendor == 0x993 && dev->descriptor.idProduct == 0x1) {
+ hDevice = usb_open(dev);
+ cerr << "Found eBook. Attempting to open... ";
+ found = 1;
+ if (hDevice) {
+// if (!usb_get_string_simple(hDevice, dev->descriptor.iSerialNumber, string, sizeof(string))) throw DevOpenError();
+ cerr << "Success.\n";
+// cerr << "Serial number: " << string << endl;
+ }
+ else throw DevOpenError();
+ }
+ }
+ }
+ if (!found) throw DevNotFoundError();
+
+ if (!usb_set_configuration(hDevice, 0x0)) throw DevOpenError();
+ if (!usb_claim_interface(hDevice, 0x1)) throw DevOpenError();
+
+ memTarget = INTERNAL;
+}
+
+REB1100::~REB1100(){
+ usb_release_interface(hDevice, 0x0);
+ usb_close(hDevice);
+}
+
+void REB1100::getFile(string filename, string &data) {
+ long flength = filename.length();
+ char buf[4096];
+ char zeros[4] = {0, 0, 0, 0};
+ int ret;
+ string request;
+ // first four bytes are the length of the filename
+ // (low-endian)
+ char *byte = reinterpret_cast<char*>(&flength);
+ request += *byte;
+ byte++;
+ request += *byte;
+ byte++;
+ request += *byte;
+ byte++;
+ request += *byte;
+ // the rest is the filename
+ request += filename;
+
+ // send a USB control request to tell the device what file we want
+ char *temp;
+ temp = new char[request.length()];
+ request.copy(temp, string::npos);
+ ret = usb_control_msg(hDevice, 0x42, 0x01, 0x00, 0x00, temp, request.length(), 300);
+ if (ret == -1) throw DevControlError();
+ delete temp;
+ temp = NULL;
+
+ // read the return code
+ ret = usb_control_msg(hDevice, 0xc2, 0x02, 0x00, 0x00, zeros, 4, 300);
+ if (ret == -1) throw DevControlError();
+
+ // read file from pipe
+ do {
+ ret = usb_bulk_read(hDevice, 2, buf, 4096, 1000);
+ if (ret == -1) throw DevReadError();
+ for(int i = 0; i < ret; i++) {
+ data += buf[i];
+ }
+ }
+ while(ret == 4096);
+}
+
+void REB1100::sendFile(string filename, string &data) {
+ string prefix = "";
+ if (memTarget == MEMCARD) { // prefix with \SM\ when sending to memory card
+ prefix = "\\SM\\";
+ }
+ filename = prefix + filename;
+
+ long flength = data.length();
+ long fnlength = filename.length();
+
+ // prepare initial request
+ string request;
+
+ // first four bytes are the length of the file
+ // (low-endian)
+ char *byte = reinterpret_cast<char*>(&flength);
+ request += *byte;
+ byte++;
+ request += *byte;
+ byte++;
+ request += *byte;
+ byte++;
+ request += *byte;
+
+ // next four bytes are the length of the filename
+ // (low-endian)
+ byte = reinterpret_cast<char*>(&fnlength);
+ request += *byte;
+ byte++;
+ request += *byte;
+ byte++;
+ request += *byte;
+ byte++;
+ request += *byte;
+
+ // append filename
+ request += filename;
+
+ // send message to device
+ int ret;
+ char *temp;
+ temp = new char[request.length()];
+ request.copy(temp, string::npos);
+ ret = usb_control_msg(hDevice, 0x42, 0x00, 0x00, 0x00, temp, request.length(), 3000);
+ delete temp;
+ temp = NULL;
+ if (ret == -1) throw DevControlError();
+
+ // read from device and check for error
+ char temp2[4] = {0, 0, 0, 0};
+ ret = usb_control_msg(hDevice, 0xc2, 0x03, 0x00, 0x00, temp2, 4, 3000);
+ if (ret == -1) throw DevControlError();
+ if (temp2[0] || temp2[1] || temp2[2] || temp2[3]) throw DevControlError();
+
+ // now start bulk writing to the device
+ string buf;
+ int n, offset = 0;
+ char *temp3;
+ do {
+ buf = data.substr(offset, 4096);
+ n = buf.length();
+ if (buf.length() > 0) {
+ temp3 = new char[buf.length()];
+ buf.copy(temp3, string::npos);
+// cout << "Sending block (" << n << " bytes)\n";
+ ret = usb_bulk_write(hDevice, 2, temp3, n, 3000);
+ if (ret == -1) throw DevWriteError();
+ delete temp3;
+ temp3 = NULL;
+ offset += 4096;
+ }
+ }
+ while(offset + 1 < data.length());
+ // send empty packet to signify end of file
+ ret = usb_bulk_write(hDevice, 2, 0, 0, 3000);
+ if (ret == -1) throw DevWriteError();
+}
+
+void REB1100::setTarget(bool target) {
+ memTarget = target;
+}
+
diff --git a/kstars/kstars/indi/apogee/stdafx.h b/kstars/kstars/indi/apogee/stdafx.h
new file mode 100644
index 00000000..acabaa43
--- /dev/null
+++ b/kstars/kstars/indi/apogee/stdafx.h
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#if !defined(STDAFX__INCLUDED_)
+#define STDAFX__INCLUDED_
+
+#ifdef __linux__
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#define ULONG unsigned long
+#define USHORT unsigned short
+#define PUSHORT unsigned short *
+#define BYTE unsigned char
+#define DWORD long
+#define BOOLEAN unsigned long
+#define TRUE 1
+#define FALSE 0
+#define INTERNET_OPEN_TYPE_DIRECT 1
+#define INTERNET_FLAG_NO_CACHE_WRITE 1
+#define INTERNET_FLAG_KEEP_CONNECTION 1
+#define Sleep(x) usleep(1000*x)
+#endif
+
+
+#endif
+
+
+
+
+
diff --git a/kstars/kstars/indi/apogee_caminfo.xml b/kstars/kstars/indi/apogee_caminfo.xml
new file mode 100644
index 00000000..7f3510b9
--- /dev/null
+++ b/kstars/kstars/indi/apogee_caminfo.xml
@@ -0,0 +1,40 @@
+<ApogeeSpecs>
+ <Apogee_Camera model='AP8P'>
+ <System interface='PPI' Base='0x378'>
+ <PP_Repeat>1</PP_Repeat>
+ <Cable>Short</Cable>
+ <High_Priority>True</High_Priority>
+ <Data_Bits>16</Data_Bits>
+ <Sensor>CCD</Sensor>
+ <Mode>0x2</Mode>
+ <Test>0x6</Test>
+ <Shutter_Speed>Normal</Shutter_Speed>
+ <Shutter_Bits>0x00</Shutter_Bits>
+ <MaxBinX>8</MaxBinX>
+ <MaxBinY>63</MaxBinY>
+ <Guider_Relays>False</Guider_Relays>
+ </System>
+
+ <Geometry Columns='1043' Rows='1033'>
+ <ImgCols>1024</ImgCols>
+ <ImgRows>1024</ImgRows>
+ <BIC>12</BIC>
+ <BIR>6</BIR>
+ <SKIPC>6</SKIPC>
+ <SKIPR>2</SKIPR>
+ <HFlush>8</HFlush>
+ <VFlush>50</VFlush>
+ </Geometry>
+
+ <Temp Control='True' Target='-30.0' Cal='165' Scale='2.1' />
+
+ <CCD Sensor='SI-003a'>
+ <Color>False</Color>
+ <Noise>10.0</Noise>
+ <Gain>3.5</Gain>
+ <PixelXSize>24</PixelXSize>
+ <PixelYSize>24</PixelYSize>
+ </CCD>
+ </Apogee_Camera>
+</ApogeeSpecs>
+
diff --git a/kstars/kstars/indi/apogee_ppi.cpp b/kstars/kstars/indi/apogee_ppi.cpp
new file mode 100644
index 00000000..9898018f
--- /dev/null
+++ b/kstars/kstars/indi/apogee_ppi.cpp
@@ -0,0 +1,1524 @@
+#if 0
+ FLI CCD
+ INDI Interface for Apogee PPI
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include <ctype.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <zlib.h>
+
+#include "apogee_ppi.h"
+#include "lilxml.h"
+#include "base64.h"
+
+static void ISPoll(void *);
+
+extern char* me; /* argv[0] */
+ApogeeCam *MainCam = NULL; /* Main and only camera */
+
+/* send client definitions of all properties */
+void ISInit()
+{
+ if (MainCam == NULL)
+ {
+ MainCam = new ApogeeCam();
+ IEAddTimer (POLLMS, ISPoll, NULL);
+ }
+}
+
+void ISGetProperties (const char *dev)
+{
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ ISInit();
+
+ MainCam->ISGetProperties(dev);
+}
+
+
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+
+ /* ignore if not ours */
+ if (dev && strcmp (dev, mydev))
+ return;
+
+ ISInit();
+
+ MainCam->ISNewSwitch(dev, name, states, names, n);
+}
+
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+ /* ignore if not ours */
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ ISInit();
+
+ MainCam->ISNewText(dev, name, texts, names, n);
+}
+
+
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+
+ /* ignore if not ours */
+ if (dev && strcmp (dev, mydev))
+ return;
+
+ ISInit();
+
+ MainCam->ISNewNumber(dev, name, values, names, n);
+}
+
+void ISNewBLOB (const char */*dev*/, const char */*name*/, int */*sizes[]*/, char **/*blobs[]*/, char **/*formats[]*/, char **/*names[]*/, int /*n*/)
+{
+
+}
+
+void ISPoll(void *)
+{
+ MainCam->ISPoll();
+ IEAddTimer (POLLMS, ISPoll, NULL);
+}
+
+
+ApogeeCam::ApogeeCam()
+{
+ ApogeeModelS = NULL;
+
+ initProperties();
+
+}
+
+ApogeeCam::~ApogeeCam()
+{
+
+}
+
+void ApogeeCam::initProperties()
+{
+ fillSwitch(&PowerS[0], "CONNECT", "Connect", ISS_OFF);
+ fillSwitch(&PowerS[1], "DISCONNECT", "Disconnect", ISS_ON);
+ fillSwitchVector(&PowerSP, PowerS, NARRAY(PowerS), mydev, "CONNECTION", "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
+
+ fillSwitch(&FrameTypeS[0], "FRAME_LIGHT", "Light", ISS_ON);
+ fillSwitch(&FrameTypeS[1], "FRAME_BIAS", "Bias", ISS_OFF);
+ fillSwitch(&FrameTypeS[2], "FRAME_DARK", "Dark", ISS_OFF);
+ fillSwitch(&FrameTypeS[3], "FRAME_FLAT", "Flat Field", ISS_OFF);
+ fillSwitchVector(&FrameTypeSP, FrameTypeS, NARRAY(FrameTypeS), mydev, "CCD_FRAME_TYPE", "Frame Type", EXPOSE_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
+
+ fillNumber(&FrameN[0], "X", "X", "%.0f", 0., MAX_PIXELS, 1., 0.);
+ fillNumber(&FrameN[1], "Y", "Y", "%.0f", 0., MAX_PIXELS, 1., 0.);
+ fillNumber(&FrameN[2], "WIDTH", "Width", "%.0f", 0., MAX_PIXELS, 1., 0.);
+ fillNumber(&FrameN[3], "HEIGHT", "Height", "%.0f", 0., MAX_PIXELS, 1., 0.);
+ fillNumberVector(&FrameNP, FrameN, NARRAY(FrameN), mydev, "CCD_FRAME", "Frame", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
+
+ fillNumber(&BinningN[0], "HOR_BIN", "X", "%0.f", 1., MAXHBIN, 1., 1.);
+ fillNumber(&BinningN[1], "VER_BIN", "Y", "%0.f", 1., MAXVBIN, 1., 1.);
+ fillNumberVector(&BinningNP, BinningN, NARRAY(BinningN), mydev, "CCD_BINNING", "Binning", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
+
+ fillNumber(&ExposeTimeN[0], "DURATION", "Duration (s)", "%5.2f", 0., 36000., 0.5, 1.);
+ fillNumberVector(&ExposeTimeNP, ExposeTimeN, NARRAY(ExposeTimeN), mydev, "CCD_EXPOSE_DURATION", "Expose", EXPOSE_GROUP, IP_RW, 60, IPS_IDLE);
+
+ fillNumber(&TemperatureN[0], "TEMPERATURE", "Temperature", "%+06.2f", MIN_CCD_TEMP, MAX_CCD_TEMP, 0.2, 0.);
+ fillNumberVector(&TemperatureNP, TemperatureN, NARRAY(TemperatureN), mydev, "CCD_TEMPERATURE", "Expose", EXPOSE_GROUP, IP_RW, 60, IPS_IDLE);
+
+ strcpy(imageB.name, "CCD1");
+ strcpy(imageB.label, "Feed");
+ strcpy(imageB.format, "");
+ imageB.blob = 0;
+ imageB.bloblen = 0;
+ imageB.size = 0;
+ imageB.bvp = 0;
+ imageB.aux0 = 0;
+ imageB.aux1 = 0;
+ imageB.aux2 = 0;
+
+ strcpy(imageBP.device, mydev);
+ strcpy(imageBP.name, "Video");
+ strcpy(imageBP.label, "Video");
+ strcpy(imageBP.group, COMM_GROUP);
+ strcpy(imageBP.timestamp, "");
+ imageBP.p = IP_RO;
+ imageBP.timeout = 0;
+ imageBP.s = IPS_IDLE;
+ imageBP.bp = &imageB;
+ imageBP.nbp = 1;
+ imageBP.aux = 0;
+
+ //loadXMLModel();
+}
+
+bool ApogeeCam::loadXMLModel()
+{
+ LilXML *XMLParser = newLilXML();
+ XMLEle *root = NULL, *camera = NULL;
+ XMLAtt *modelName;
+ FILE *modelSpecFile = NULL;
+ char errmsg[1024];
+ int ncams = 0;
+
+ //IDLog("Top dir is "TOP_DATADIR, NULL);
+ modelSpecFile = fopen(TOP_DATADIR"/apogee_caminfo.xml", "r");
+ //modelSpecFile = fopen("/opt/kde3/share/apps/kstars/apogee_caminfo.xml", "r");
+ if (modelSpecFile == NULL)
+ {
+ IDLog("Error: Unable to open file apogee_caminfo.xml\n");
+ IDMessage(mydev, "Error: Unable to open file apogee_caminfo.xml");
+ return false;
+ }
+
+ root = readXMLFile(modelSpecFile, XMLParser, errmsg);
+ if (root == NULL)
+ {
+ IDLog("Error: Unable to process apogee_caminfo.xml. %s\n", errmsg);
+ IDMessage(mydev, "Error: Unable to process apogee_caminfo.xml. %s\n", errmsg);
+ fclose(modelSpecFile);
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ for (camera = nextXMLEle (root, 1); camera != NULL; camera = nextXMLEle (root, 0))
+ {
+ modelName = findXMLAtt(camera, "model");
+ if (modelName == NULL)
+ continue;
+
+ ApogeeModelS = (ApogeeModelS == NULL) ? (ISwitch *) malloc (sizeof(ISwitch))
+ : (ISwitch *) realloc(ApogeeModelS, sizeof(ISwitch) * (ncams + 1));
+
+ snprintf(ApogeeModelS[ncams].name, MAXINDINAME, "Model%d", ncams);
+ strcpy(ApogeeModelS[ncams].label, valuXMLAtt(modelName));
+ ApogeeModelS[ncams].s = (ncams == 0) ? ISS_ON : ISS_OFF;
+ ApogeeModelS[ncams].svp = NULL;
+ ApogeeModelS[ncams].aux = NULL;
+
+ ncams++;
+ }
+
+ fclose(modelSpecFile);
+ delLilXML(XMLParser);
+
+ if (ncams > 0)
+ {
+ fillSwitchVector(&ApogeeModelSP, ApogeeModelS, ncams, mydev, "Model", "", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
+ return true;
+ }
+
+ return false;
+
+}
+
+void ApogeeCam::ISGetProperties(const char */*dev*/)
+{
+
+
+ /* COMM_GROUP */
+ IDDefSwitch(&PowerSP, NULL);
+ if (loadXMLModel())
+ IDDefSwitch(&ApogeeModelSP, NULL);
+ else
+ IDMessage(mydev, "Error: Unable to read camera specifications. Driver is disabled.");
+ IDDefBLOB(&imageBP, NULL);
+
+ /* Expose */
+ IDDefSwitch(&FrameTypeSP, NULL);
+ IDDefNumber(&ExposeTimeNP, NULL);
+ IDDefNumber(&TemperatureNP, NULL);
+
+ /* Image Group */
+ IDDefNumber(&FrameNP, NULL);
+ IDDefNumber(&BinningNP, NULL);
+
+ IDLog("Apogee Driver Debug Enabled\n");
+
+}
+
+void ApogeeCam::ISNewSwitch (const char */*dev*/, const char *name, ISState *states, char *names[], int n)
+{
+
+ /* Connection */
+ if (!strcmp (name, PowerSP.name))
+ {
+ IUResetSwitches(&PowerSP);
+ IUUpdateSwitches(&PowerSP, states, names, n);
+ connectCCD();
+ return;
+ }
+
+ /* Frame Type */
+ if (!strcmp(FrameTypeSP.name, name))
+ {
+ if (checkPowerS(&FrameTypeSP))
+ return;
+
+ IUResetSwitches(&FrameTypeSP);
+ IUUpdateSwitches(&FrameTypeSP, states, names, n);
+ FrameTypeSP.s = IPS_OK;
+ IDSetSwitch(&FrameTypeSP, NULL);
+
+ return;
+ }
+
+ /* Apogee Model */
+ if (!strcmp(ApogeeModelSP.name, name))
+ {
+ IUResetSwitches(&ApogeeModelSP);
+ IUUpdateSwitches(&ApogeeModelSP, states, names, n);
+ ApogeeModelSP.s = IPS_OK;
+ IDSetSwitch(&ApogeeModelSP, NULL);
+ return;
+ }
+
+}
+
+void ApogeeCam::ISNewText (const char */*dev*/, const char */*name*/, char **/*texts[]*/, char **/*names[]*/, int /*n*/)
+{
+
+}
+
+void ApogeeCam::ISNewNumber (const char */*dev*/, const char *name, double values[], char *names[], int n)
+{
+ /* Exposure time */
+ if (!strcmp (ExposeTimeNP.name, name))
+ {
+ if (checkPowerN(&ExposeTimeNP))
+ return;
+
+ if (ExposeTimeNP.s == IPS_BUSY)
+ {
+ cam->Reset();
+ ExposeTimeNP.s = IPS_IDLE;
+ ExposeTimeN[0].value = 0;
+
+ IDSetNumber(&ExposeTimeNP, "Exposure cancelled.");
+ IDLog("Exposure Cancelled.\n");
+ return;
+ }
+
+ ExposeTimeNP.s = IPS_IDLE;
+
+ IUUpdateNumbers(&ExposeTimeNP, values, names, n);
+
+ IDLog("Exposure Time is: %g\n", ExposeTimeN[0].value);
+
+ handleExposure(NULL);
+ return;
+ }
+
+ if (!strcmp(TemperatureNP.name, name))
+ {
+ if (checkPowerN(&TemperatureNP))
+ return;
+
+ TemperatureNP.s = IPS_IDLE;
+
+ if (values[0] < MIN_CCD_TEMP || values[0] > MAX_CCD_TEMP)
+ {
+ IDSetNumber(&TemperatureNP, "Error: valid range of temperature is from %d to %d", MIN_CCD_TEMP, MAX_CCD_TEMP);
+ return;
+ }
+
+ targetTemp = values[0];
+ cam->write_CoolerMode(0);
+ cam->write_CoolerMode(1);
+ cam->write_CoolerSetPoint(targetTemp);
+
+ TemperatureNP.s = IPS_BUSY;
+
+ IDSetNumber(&TemperatureNP, "Setting CCD temperature to %+06.2f C", values[0]);
+ IDLog("Setting CCD temperature to %+06.2f C\n", values[0]);
+ return;
+ }
+
+ if (!strcmp(FrameNP.name, name))
+ {
+ if (checkPowerN(&FrameNP))
+ return;
+
+ FrameNP.s = IPS_OK;
+ IUUpdateNumbers(&FrameNP, values, names, n);
+
+ cam->m_StartX = (int) FrameN[0].value;
+ cam->m_StartY = (int) FrameN[1].value;
+ cam->m_NumX = (int) FrameN[2].value;
+ cam->m_NumY = (int) FrameN[3].value;
+ IDSetNumber(&FrameNP, NULL);
+
+ } /* end FrameNP */
+
+
+ if (!strcmp(BinningNP.name, name))
+ {
+ if (checkPowerN(&BinningNP))
+ return;
+
+
+ BinningNP.s = IPS_OK;
+ IUUpdateNumbers(&BinningNP, values, names, n);
+
+ cam->m_BinX = (int) BinningN[0].value;
+ cam->m_BinY = (int) BinningN[1].value;
+
+ IDLog("Binning is: %.0f x %.0f\n", BinningN[0].value, BinningN[1].value);
+ return;
+ }
+}
+
+
+void ApogeeCam::ISPoll()
+{
+ static int mtc=5;
+ int readStatus=0;
+ double ccdTemp;
+
+ if (!isCCDConnected())
+ return;
+
+ switch (ExposeTimeNP.s)
+ {
+ case IPS_IDLE:
+ case IPS_OK:
+ break;
+
+ case IPS_BUSY:
+
+ readStatus = cam->read_Status();
+ if (readStatus < 0)
+ {
+ IDLog("Error in exposure! Read status: %d\n", readStatus);
+ ExposeTimeNP.s = IPS_ALERT;
+ ExposeTimeN[0].value = 0;
+ IDSetNumber(&ExposeTimeNP, "Error in exposure procedure. Read states: %d", readStatus);
+ return;
+ }
+ else if (readStatus == Camera_Status_ImageReady)
+ {
+ ExposeTimeN[0].value = 0;
+ ExposeTimeNP.s = IPS_OK;
+ IDSetNumber(&ExposeTimeNP, "Exposure done, downloading image...");
+ IDLog("Exposure done, downloading image...\n");
+ /* grab and save image */
+ grabImage();
+ return;
+ }
+
+ ExposeTimeN[0].value --;
+ IDSetNumber(&ExposeTimeNP, NULL);
+ break;
+
+ case IPS_ALERT:
+ break;
+ }
+
+ switch (TemperatureNP.s)
+ {
+ case IPS_IDLE:
+ case IPS_OK:
+ mtc--;
+
+ if (mtc == 0)
+ {
+ TemperatureN[0].value = cam->read_Temperature();
+ IDSetNumber(&TemperatureNP, NULL);
+ mtc = 5;
+ }
+ break;
+
+ case IPS_BUSY:
+
+ ccdTemp = cam->read_Temperature();
+
+ if (fabs(targetTemp - ccdTemp) <= TEMP_THRESHOLD)
+ TemperatureNP.s = IPS_OK;
+
+ mtc = 1;
+ TemperatureN[0].value = ccdTemp;
+ IDSetNumber(&TemperatureNP, NULL);
+ break;
+
+ case IPS_ALERT:
+ break;
+ }
+
+}
+
+/* Downloads the image from the CCD row by row and store them
+ in a raw file.
+ N.B. No processing is done on the image */
+void ApogeeCam::grabImage()
+{
+
+ long err;
+ int img_size, fd;
+ char errmsg[1024];
+ char filename[] = "/tmp/fitsXXXXXX";
+
+ IDLog("In grab Image\n");
+
+ if ((fd = mkstemp(filename)) < 0)
+ {
+ IDMessage(mydev, "Error making temporary filename.");
+ IDLog("Error making temporary filename.\n");
+ return;
+ }
+ close(fd);
+
+ img_size = APGFrame.width * APGFrame.height * sizeof(unsigned short);
+
+ IDLog("Allocating memory buffer. Width: %d - Height: %d\n", APGFrame.width, APGFrame.height);
+
+ APGFrame.img = (unsigned short *) malloc (img_size);
+
+ if (APGFrame.img == NULL)
+ {
+ IDMessage(mydev, "Not enough memory to store image.");
+ IDLog("Not enough memory to store image.\n");
+ return;
+ }
+
+ IDLog("Getting frame buffer from camera...\n");
+ if (!cam->GetImage( APGFrame.img , APGFrame.width, APGFrame.height ))
+ {
+ free(APGFrame.img);
+ IDMessage(mydev, "GetImage() failed.");
+ IDLog("GetImage() failed.");
+ return;
+ }
+
+ IDLog("Done with getting frame buffer, writing FITS file\n");
+
+ err = writeFITS(filename, errmsg);
+
+ if (err)
+ {
+ free(APGFrame.img);
+ IDMessage(mydev, errmsg, NULL);
+ return;
+ }
+
+ free(APGFrame.img);
+
+ IDLog("All good, returning\n");
+
+}
+
+int ApogeeCam::writeFITS(char *filename, char errmsg[])
+{
+
+ FITS_FILE* ofp;
+ int bpp, bpsl, width, height;
+ long nbytes;
+ FITS_HDU_LIST *hdu;
+
+ IDLog("in write FITS, opening filename %s\n", filename);
+
+ ofp = fits_open (filename, "w");
+ if (!ofp)
+ {
+ sprintf(errmsg, "Error: cannot open file for writing.");
+ return (-1);
+ }
+
+ width = APGFrame.width;
+ height = APGFrame.height;
+ bpp = sizeof(unsigned short); /* Bytes per Pixel */
+ bpsl = bpp * APGFrame.width; /* Bytes per Line */
+ nbytes = 0;
+
+ IDLog("Creating FITS header\n");
+ hdu = create_fits_header (ofp, width, height, bpp);
+ if (hdu == NULL)
+ {
+ sprintf(errmsg, "Error: creating FITS header failed.");
+ return (-1);
+ }
+ if (fits_write_header (ofp, hdu) < 0)
+ {
+ sprintf(errmsg, "Error: writing to FITS header failed.");
+ return (-1);
+ }
+
+ IDLog("Converting to BIG Endian\n");
+ for (int i=0; i < height; i++)
+ for (int j=0 ; j < width; j++)
+ APGFrame.img[width * i + j] = getBigEndian( (APGFrame.img[width * i + j]) );
+
+ IDLog("Writing frame to disk\n");
+ for (int i= 0; i < height ; i++)
+ {
+ fwrite(APGFrame.img + (i * width), 2, width, ofp->fp);
+ nbytes += bpsl;
+ }
+
+ IDLog("Calculating nbytes\n");
+ nbytes = nbytes % FITS_RECORD_SIZE;
+ if (nbytes)
+ {
+ while (nbytes++ < FITS_RECORD_SIZE)
+ putc (0, ofp->fp);
+ }
+
+ if (ferror (ofp->fp))
+ {
+ sprintf(errmsg, "Error: write error occured");
+ return (-1);
+ }
+
+ IDLog("Closing ofp\n");
+ fits_close (ofp);
+
+ /* Success */
+ ExposeTimeNP.s = IPS_OK;
+ IDSetNumber(&ExposeTimeNP, NULL);
+ IDLog("Loading FITS image...\n");
+
+ IDLog("Uploading filename\n");
+ uploadFile(filename);
+ IDLog("Uploading done, returning\n");
+
+ return 0;
+
+}
+
+void ApogeeCam::uploadFile(char * filename)
+{
+
+ FILE * fitsFile;
+ unsigned char *fitsData, *compressedData;
+ int r=0;
+ unsigned int i =0, nr = 0;
+ uLongf compressedBytes=0;
+ uLong totalBytes;
+ struct stat stat_p;
+
+ IDLog("in upload file, will stat file now\n");
+
+ if ( -1 == stat (filename, &stat_p))
+ {
+ IDLog(" Error occoured attempting to stat %s\n", filename);
+ return;
+ }
+
+ totalBytes = stat_p.st_size;
+ fitsData = (unsigned char *) malloc (sizeof(unsigned char) * totalBytes);
+ compressedData = (unsigned char *) malloc (sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
+
+ if (fitsData == NULL || compressedData == NULL)
+ {
+ IDLog("Error! low memory. Unable to initialize fits buffers.\n");
+ return;
+ }
+
+ IDLog("opening file\n");
+ fitsFile = fopen(filename, "r");
+
+ if (fitsFile == NULL)
+ return;
+
+ IDLog("Reading file from disk\n");
+ /* #1 Read file from disk */
+ for (i=0; i < totalBytes; i+= nr)
+ {
+ nr = fread(fitsData + i, 1, totalBytes - i, fitsFile);
+
+ if (nr <= 0)
+ {
+ IDLog("Error reading temporary FITS file.\n");
+ return;
+ }
+ }
+
+ compressedBytes = sizeof(char) * totalBytes + totalBytes / 64 + 16 + 3;
+
+ IDLog("Compressing data\n");
+ /* #2 Compress it */
+ r = compress2(compressedData, &compressedBytes, fitsData, totalBytes, 9);
+ if (r != Z_OK)
+ {
+ /* this should NEVER happen */
+ IDLog("internal error - compression failed: %d\n", r);
+ return;
+ }
+
+ IDLog("Sending blob. bloblen %ld - size %ld\n", compressedBytes, totalBytes);
+
+ /* #3 Send it */
+ imageB.blob = compressedData;
+ imageB.bloblen = compressedBytes;
+ imageB.size = totalBytes;
+ strcpy(imageB.format, ".fits.z");
+ imageBP.s = IPS_OK;
+ IDSetBLOB (&imageBP, NULL);
+
+ free (fitsData);
+ free (compressedData);
+
+}
+
+/* Initiates the exposure procedure */
+void ApogeeCam::handleExposure(void */*p*/)
+{
+
+ int curFrame = getOnSwitch(&FrameTypeSP);
+
+ switch (curFrame)
+ {
+ /* Light frame */
+ case LIGHT_FRAME:
+ if (!cam->Expose( (int) ExposeTimeN[0].value, true ))
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ IDSetNumber(&ExposeTimeNP, "Light Camera exposure failed.");
+ IDLog("Light Camera exposure failed.\n");
+ return;
+ }
+ break;
+
+ /* BIAS frame is the same as DARK but with minimum period. i.e. readout from camera electronics.
+ */
+ case BIAS_FRAME:
+ if (!cam->Expose( 0.05 , false ))
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ IDSetNumber(&ExposeTimeNP, "Bias Camera exposure failed.");
+ IDLog("Bias Camera exposure failed.\n");
+ return;
+ }
+ break;
+
+ /* Dark frame */
+ case DARK_FRAME:
+ if (!cam->Expose( (int) ExposeTimeN[0].value , false ))
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ IDSetNumber(&ExposeTimeNP, "Dark Camera exposure failed.");
+ IDLog("Dark Camera exposure failed.\n");
+ return;
+ }
+ break;
+
+ case FLAT_FRAME:
+ if (!cam->Expose( (int) ExposeTimeN[0].value , true ))
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ IDSetNumber(&ExposeTimeNP, "Flat Camera exposure failed.");
+ IDLog("Flat Camera exposure failed.\n");
+ return;
+ }
+ break;
+ }
+
+ APGFrame.frameType = curFrame;
+ APGFrame.width = (int) FrameN[2].value;
+ APGFrame.height = (int) FrameN[3].value;
+ APGFrame.expose = (int) ExposeTimeN[0].value;
+ APGFrame.temperature = TemperatureN[0].value;
+ APGFrame.binX = (int) BinningN[0].value;
+ APGFrame.binY = (int) BinningN[1].value;
+
+ ExposeTimeNP.s = IPS_BUSY;
+
+ IDSetNumber(&ExposeTimeNP, "Taking a %g seconds frame...", ExposeTimeN[0].value);
+ IDLog("Taking a frame. Width: %d - Height: %d - expose %d - temperature %g - binX %d - binY %d\n", APGFrame.width, APGFrame.height, APGFrame.expose, APGFrame.temperature, APGFrame.binX, APGFrame.binY);
+
+}
+
+/* Retrieves basic data from the CCD upon connection like temperature, array size, firmware..etc */
+void ApogeeCam::getBasicData()
+{
+
+
+ // Maximum resolution
+ FrameN[2].max = cam->m_NumX;
+ FrameN[3].max = cam->m_NumY;
+ IUUpdateMinMax(&FrameNP);
+
+ // Maximum Bin
+ BinningN[0].max = cam->m_MaxBinX;
+ BinningN[1].max = cam->m_MaxBinX;
+ IUUpdateMinMax(&BinningNP);
+
+ FrameN[0].value = 0;
+ FrameN[1].value = 0;
+ FrameN[2].min = 0;
+ FrameN[2].max = cam->m_ImgColumns;
+ FrameN[2].value = cam->m_ImgColumns;
+ FrameN[3].min = 0;
+ FrameN[3].max = cam->m_ImgRows;
+ FrameN[3].value = cam->m_ImgRows;
+
+ IUUpdateMinMax(&FrameNP);
+ IDSetNumber(&FrameNP, NULL);
+
+ // Current Temperature
+ TemperatureN[0].value = cam->read_Temperature();
+ IDSetNumber(&TemperatureNP, NULL);
+
+}
+
+int ApogeeCam::getOnSwitch(ISwitchVectorProperty *sp)
+{
+ int i=0;
+ for (i=0; i < sp->nsp ; i++)
+ {
+ /*IDLog("Switch %s is %s\n", sp->sp[i].name, sp->sp[i].s == ISS_ON ? "On" : "Off");*/
+ if (sp->sp[i].s == ISS_ON)
+ return i;
+ }
+
+ return -1;
+}
+
+int ApogeeCam::checkPowerS(ISwitchVectorProperty *sp)
+{
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(sp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", sp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", sp->label);
+
+ sp->s = IPS_IDLE;
+ IDSetSwitch(sp, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int ApogeeCam::checkPowerN(INumberVectorProperty *np)
+{
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(np->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", np->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", np->label);
+
+ np->s = IPS_IDLE;
+ IDSetNumber(np, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int ApogeeCam::checkPowerT(ITextVectorProperty *tp)
+{
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(tp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", tp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", tp->label);
+
+ tp->s = IPS_IDLE;
+ IDSetText(tp, NULL);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+void ApogeeCam::connectCCD()
+{
+
+ /* USB by default {USB, SERIAL, PARALLEL, INET} */
+ switch (PowerS[0].s)
+ {
+ case ISS_ON:
+ if (initCamera())
+ {
+ /* Sucess! */
+ PowerS[0].s = ISS_ON;
+ PowerS[1].s = ISS_OFF;
+ PowerSP.s = IPS_OK;
+ IDSetSwitch(&PowerSP, "CCD is online. Retrieving basic data.");
+ IDLog("CCD is online. Retrieving basic data.\n");
+ getBasicData();
+
+ }
+ else
+ {
+ PowerSP.s = IPS_IDLE;
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch(&PowerSP, "Error: no cameras were detected.");
+ IDLog("Error: no cameras were detected.\n");
+ return;
+ }
+
+ break;
+
+ case ISS_OFF:
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_IDLE;
+ IDSetSwitch(&PowerSP, "CCD is offline.");
+ break;
+ }
+
+}
+
+bool ApogeeCam::initCamera()
+{
+ LilXML *XMLParser = newLilXML();
+ XMLEle *root = NULL, *camera = NULL, *ele = NULL;
+ XMLEle *system = NULL, *geometry = NULL, *temp = NULL, *ccd = NULL;
+ XMLAtt *ap;
+ FILE *spFile = NULL;
+ char errmsg[1024];
+
+ spFile = fopen(TOP_DATADIR"/apogee_caminfo.xml", "r");
+ //spFile = fopen("/opt/kde3/share/apps/kstars/apogee_caminfo.xml", "r");
+ if (spFile == NULL)
+ {
+ IDLog("Error: Unable to open file apogee_caminfo.xml\n");
+ IDMessage(mydev, "Error: Unable to open file apogee_caminfo.xml");
+ return false;
+ }
+
+ root = readXMLFile(spFile, XMLParser, errmsg);
+ if (root == NULL)
+ {
+ IDLog("Error: Unable to process apogee_caminfo.xml. %s\n", errmsg);
+ IDMessage(mydev, "Error: Unable to process apogee_caminfo.xml. %s\n", errmsg);
+ fclose(spFile);
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ fclose(spFile);
+
+ // Let's locate which camera to load the configuration for
+ camera = findXMLEle(root, "Apogee_Camera");
+
+ if (camera == NULL)
+ {
+ IDLog("Error: Unable to find Apogee_Camera element.\n");
+ IDMessage(mydev, "Error: Unable to find Apogee_Camera element.");
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ IDLog("Looking for %s - len %d\n", ApogeeModelS[getOnSwitch(&ApogeeModelSP)].label, strlen(ApogeeModelS[getOnSwitch(&ApogeeModelSP)].label));
+
+ ap = findXMLAtt(camera, "model");
+ if (!ap)
+ {
+ IDLog("Error: Unable to find attribute model.\n");
+ IDMessage(mydev, "Error: Unable to find attribute model.");
+ return false;
+ }
+
+ if (strcmp(valuXMLAtt(ap), ApogeeModelS[getOnSwitch(&ApogeeModelSP)].label))
+ {
+ IDLog("Camera %s not found in XML file\n", ApogeeModelS[getOnSwitch(&ApogeeModelSP)].label);
+ IDMessage(mydev, "Camera %s not found in XML file\n", ApogeeModelS[getOnSwitch(&ApogeeModelSP)].label);
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ // Let's get the subsections now
+ system = findXMLEle(camera, "System");
+ geometry = findXMLEle(camera, "Geometry");
+ temp = findXMLEle(camera, "Temp");
+ ccd = findXMLEle(camera, "CCD");
+
+ if (system == NULL)
+ {
+ IDLog("Error: Unable to find System element in camera.\n");
+ IDMessage(mydev, "Error: Unable to find System element in camera.");
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ if (geometry == NULL)
+ {
+ IDLog("Error: Unable to find Geometry element in camera.\n");
+ IDMessage(mydev, "Error: Unable to find Geometry element in camera.");
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ if (temp == NULL)
+ {
+ IDLog("Error: Unable to find Temp element in camera.\n");
+ IDMessage(mydev, "Error: Unable to find Temp element in camera.");
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ if (ccd == NULL)
+ {
+ IDLog("Error: Unable to find CCD element in camera.\n");
+ IDMessage(mydev, "Error: Unable to find CCD element in camera.");
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ cam = new CCameraIO();
+
+ if (cam == NULL)
+ {
+ IDLog("Error: Failed to create CCameraIO object.\n");
+ IDMessage(mydev, "Error: Failed to create CCameraIO object.");
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ int bAddr = 0x378;
+ int val = 0;
+
+ bAddr = hextoi(valuXMLAtt(findXMLAtt(system, "Base"))) & 0xFFF;
+
+ // Rows
+ ap = findXMLAtt(geometry, "Rows");
+ if (!ap)
+ {
+ IDLog("Error: Unable to find attribute Rows.\n");
+ IDMessage(mydev, "Error: Unable to find attribute Rows.");
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ cam->m_Rows = hextoi(valuXMLAtt(ap));
+
+ // Columns
+ ap = findXMLAtt(geometry, "Columns");
+ if (!ap)
+ {
+ IDLog("Error: Unable to find attribute Columns.\n");
+ IDMessage(mydev, "Error: Unable to find attribute Columns.");
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ cam->m_Columns = hextoi(valuXMLAtt(ap));
+
+ // pp_repeat
+ ele = findXMLEle(system, "PP_Repeat");
+ if (!ele)
+ {
+ IDLog("Error: Unable to find element PP_Repeat.\n");
+ IDMessage(mydev, "Error: Unable to find element PP_Repeat.");
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ val = hextoi(pcdataXMLEle(ele));
+ if (val > 0 && val <= 1000)
+ cam->m_PPRepeat = val;
+
+ // Initiate driver
+ if (!cam->InitDriver(0))
+ {
+ IDLog("Error: Failed to Init Driver.\n");
+ IDMessage(mydev, "Error: Failed to Init Driver.");
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ cam->Reset();
+
+ // Cable length
+ ele = findXMLEle(system, "Cable");
+ if (!ele)
+ {
+ IDLog("Error: Unable to find element Cable.\n");
+ IDMessage(mydev, "Error: Unable to find element Cable.");
+ delLilXML(XMLParser);
+ return false;
+ }
+
+ if (!strcmp("Long", pcdataXMLEle(ele)))
+ {
+ cam->write_LongCable( true );
+ IDLog("Cable is long\n");
+ }
+ else
+ {
+ cam->write_LongCable( false );
+ IDLog("Cable is short\n");
+ }
+
+
+ if (!cam->read_Present())
+ {
+ IDLog("Error: read_Present() failed.\n");
+ IDMessage(mydev, "Error: read_Present() failed.");
+ delLilXML(XMLParser);
+ return false;
+}
+
+ // Default settings
+ cam->write_UseTrigger( false );
+ cam->write_ForceShutterOpen( false );
+
+ // High priority
+ ele = findXMLEle(system, "High_Priority");
+ if (ele)
+ {
+ if (!strcmp(pcdataXMLEle(ele), "True"))
+ cam->m_HighPriority = true;
+ else
+ cam->m_HighPriority = false;
+ }
+
+ // Data bits
+ ele = findXMLEle(system, "Data_Bits");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele));
+ if (val >= 8 && val <= 18) cam->m_DataBits = val;
+ }
+
+ // Sensor
+ ele = findXMLEle(system, "Sensor");
+ if (ele)
+ {
+ if (!strcmp(pcdataXMLEle(ele), "CCD"))
+ cam->m_SensorType = Camera_SensorType_CCD;
+ else
+ cam->m_SensorType = Camera_SensorType_CMOS;
+ }
+
+ // Mode
+ ele = findXMLEle(system, "Mode");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele)) & 0xF;
+ cam->write_Mode( val );
+ IDLog("Mode %d\n", val);
+ }
+ else
+ cam->write_Mode( 0 );
+
+ // Test
+ ele = findXMLEle(system, "Test");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele)) & 0xF;
+ cam->write_TestBits( val );
+ IDLog("Test bits %d\n", val);
+ }
+ else
+ cam->write_TestBits( 0 );
+
+ // Test2
+ ele = findXMLEle(system, "Test2");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele)) & 0xF;
+ cam->write_Test2Bits( val );
+ IDLog("Test 2 bits %d\n", val);
+ }
+ else
+ cam->write_Test2Bits( 0 );
+
+ // Shutter Speed
+ ele = findXMLEle(system, "Shutter_Speed");
+ if (ele)
+ {
+ cam->m_MaxExposure = 10485.75;
+
+ if (!strcmp(pcdataXMLEle(ele), "Normal"))
+ {
+ cam->m_FastShutter = false;
+ cam->m_MinExposure = 0.01;
+ IDLog("Shutter speed normal\n");
+ }
+ else if ( (!strcmp(pcdataXMLEle(ele), "Fast")) || (!strcmp(pcdataXMLEle(ele), "Dual")) )
+ {
+ cam->m_FastShutter = true;
+ cam->m_MinExposure = 0.001;
+ IDLog("Shutter speed fast\n");
+ }
+ }
+
+ // Shutter Bits
+ ele = findXMLEle(system, "Shutter_Bits");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele));
+ cam->m_FastShutterBits_Mode = val & 0x0F;
+ cam->m_FastShutterBits_Test = ( val & 0xF0 ) >> 4;
+ IDLog("Shutter bits %d\n", val);
+ }
+
+ // Max X Bin
+ ele = findXMLEle(system, "MaxBinX");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele));
+ if (val >= 1 && val <= MAXHBIN)
+ cam->m_MaxBinX = val;
+ }
+
+ // Max Y Bin
+ ele = findXMLEle(system, "MaxBinY");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele));
+ if (val >= 1 && val <= MAXVBIN)
+ cam->m_MaxBinY = val;
+ }
+
+ // Guider Relays
+ ele = findXMLEle(system, "Guider_Relays");
+ if (ele)
+ {
+ if (!strcmp(pcdataXMLEle(ele), "True"))
+ cam->m_GuiderRelays = true;
+ else
+ cam->m_GuiderRelays = false;
+ }
+
+ // Timeout
+ ele = findXMLEle(system, "Timeout");
+ if (ele)
+ {
+ double dval = atof(pcdataXMLEle(ele));
+ if (dval >= 0.0 && dval <= 10000.0) cam->m_Timeout = dval;
+ }
+
+ // BIC
+ ele = findXMLEle(geometry, "BIC");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele));
+ if (val >= 1 && val <= MAXCOLUMNS)
+ cam->m_BIC = val;
+ }
+
+ // BIR
+ ele = findXMLEle(geometry, "BIR");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele));
+ if (val >= 1 && val <= MAXROWS)
+ cam->m_BIR = val;
+ }
+
+ // SKIPC
+ ele = findXMLEle(geometry, "SKIPC");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele));
+ if (val >= 1 && val <= MAXCOLUMNS)
+ cam->m_SkipC = val;
+ }
+
+ // SKIPR
+ ele = findXMLEle(geometry, "SKIPR");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele));
+ if (val >= 1 && val <= MAXROWS)
+ cam->m_SkipR = val;
+ }
+
+ // IMG COlS
+ ele = findXMLEle(geometry, "ImgCols");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele));
+ if (val >= 1 && val <= MAXTOTALCOLUMNS)
+ cam->m_ImgColumns = val;
+ }
+ else
+ cam->m_ImgColumns = cam->m_Columns - cam->m_BIC - cam->m_SkipC;
+
+ // IMG ROWS
+ ele = findXMLEle(geometry, "ImgRows");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele));
+ if (val >= 1 && val <= MAXTOTALROWS)
+ cam->m_ImgRows = val;
+ }
+ else
+ cam->m_ImgRows = cam->m_Rows - cam->m_BIR - cam->m_SkipR;
+
+ // Hor Flush
+ ele = findXMLEle(geometry, "HFlush");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele));
+ if (val >= 1 && val <= MAXHBIN)
+ cam->m_HFlush = val;
+ }
+
+ // Ver Flush
+ ele = findXMLEle(geometry, "VFlush");
+ if (ele)
+ {
+ val = hextoi(pcdataXMLEle(ele));
+ if (val >= 1 && val <= MAXVBIN)
+ cam->m_VFlush = val;
+ }
+
+ // Default to full frame
+ cam->m_NumX = cam->m_ImgColumns;
+ cam->m_NumY = cam->m_ImgRows;
+
+ // Temp Control
+ ap = findXMLAtt(temp, "Control");
+ if (ap)
+ {
+ if (!strcmp(valuXMLAtt(ap), "True"))
+ cam->m_TempControl = true;
+ else
+ cam->m_TempControl = false;
+ }
+
+ // Calibration
+ ap = findXMLAtt(temp, "Cal");
+ if (ap)
+ {
+ val = hextoi(valuXMLAtt(ap));
+ if (val >= 1 && val <= 255)
+ cam->m_TempCalibration = val;
+ }
+
+ // Scale
+ ap = findXMLAtt(temp, "Scale");
+ if (ap)
+ {
+ double dval = atof(valuXMLAtt(ap));
+ if (dval >= 1.0 && dval <= 10.0)
+ cam->m_TempScale = dval;
+ }
+
+ // Target
+ ap = findXMLAtt(temp, "Target");
+ if (ap)
+ {
+ double dval = atof(valuXMLAtt(ap));
+ if (dval >= -60.0 && dval <= 40.0)
+ cam->write_CoolerSetPoint( dval );
+ else
+ cam->write_CoolerSetPoint( -10.0 ); // Default
+
+ IDLog("Target: %g\n", dval);
+ }
+
+ // Sensor
+ ap = findXMLAtt(ccd, "Sensor");
+ if (ap)
+ {
+ strncpy (cam->m_Sensor, valuXMLAtt(ap), 255);
+ IDLog("Sensor: %s\n", cam->m_Sensor);
+ }
+
+ // Color
+ ele = findXMLEle(ccd, "Color");
+ if (ele)
+ {
+ if (!strcmp(pcdataXMLEle(ele), "True"))
+ {
+ cam->m_Color = true;
+ IDLog("Color: true\n");
+ }
+ else
+ {
+ cam->m_Color = false;
+ IDLog("Color: false\n");
+ }
+ }
+
+ // Noise
+ ele = findXMLEle(ccd, "Noise");
+ if (ele)
+ cam->m_Noise = atof( pcdataXMLEle(ele) );
+
+ // Noise
+ ele = findXMLEle(ccd, "Gain");
+ if (ele)
+ cam->m_Gain = atof( pcdataXMLEle(ele) );
+
+ // Pixel X Size
+ ele = findXMLEle(ccd, "PixelXSize");
+ if (ele)
+ {
+ cam->m_PixelXSize = atof( pcdataXMLEle(ele) );
+ IDLog("Pixel X Size: %g\n", cam->m_PixelXSize);
+ }
+
+ // Pixel Y Size
+ ele = findXMLEle(ccd, "PixelYSize");
+ if (ele)
+ {
+ cam->m_PixelYSize = atof( pcdataXMLEle(ele) );
+ IDLog("Pixel Y Size: %g\n", cam->m_PixelYSize);
+ }
+
+ // Log all values
+ IDLog("Cam Row: %d - Cam Cols: %d - PP_Repeat %d\n",cam->m_Rows, cam->m_Columns, cam->m_PPRepeat);
+ IDLog("High_Priority %s - Data_Bits %d - Sensor %s\n", cam->m_HighPriority ? "true" : "false", cam->m_DataBits, (cam->m_SensorType == Camera_SensorType_CCD) ? "CCD" : "CMOS");
+ IDLog("Max X Bin: %d - Max Y Bin: %d - Guider Relays: %s\n", cam->m_MaxBinX, cam->m_MaxBinY, cam->m_GuiderRelays ? "true" : "false");
+ IDLog("BIC: %d - BIR: %d - SKIPC: %d - SKIPR: %d - ImgRows: %d - ImgCols %d\n", cam->m_BIC, cam->m_BIR, cam->m_SkipC, cam->m_SkipR, cam->m_ImgRows, cam->m_ImgColumns);
+ IDLog("HFlush: %d - VFlush: %d - Control: %s - Cal: %d - Scale: %g\n", cam->m_HFlush, cam->m_VFlush, cam->m_TempControl ? "true" : "false", cam->m_TempCalibration, cam->m_TempScale);
+
+ delLilXML(XMLParser);
+
+ return true;
+}
+
+/* isCCDConnected: return 1 if we have a connection, 0 otherwise */
+int ApogeeCam::isCCDConnected(void)
+{
+ return ((PowerS[0].s == ISS_ON) ? 1 : 0);
+}
+
+FITS_HDU_LIST * ApogeeCam::create_fits_header (FITS_FILE *ofp, uint width, uint height, uint bpp)
+{
+
+ FITS_HDU_LIST *hdulist;
+
+ char temp_s[FITS_CARD_SIZE], expose_s[FITS_CARD_SIZE], binning_s[FITS_CARD_SIZE], frame_s[FITS_CARD_SIZE], pixel_s[FITS_CARD_SIZE];
+ char obsDate[FITS_CARD_SIZE];
+
+ snprintf(obsDate, FITS_CARD_SIZE, "DATE-OBS= '%s' /Observation Date UTC", timestamp());
+
+ hdulist = fits_add_hdu (ofp);
+ if (hdulist == NULL) return (NULL);
+
+ hdulist->used.simple = 1;
+ hdulist->bitpix = 16;
+ hdulist->naxis = 2;
+ hdulist->naxisn[0] = width;
+ hdulist->naxisn[1] = height;
+ hdulist->naxisn[2] = bpp;
+ hdulist->used.datamin = 1;
+ hdulist->datamin = min();
+ hdulist->used.datamax = 1;
+ hdulist->datamax = max();
+ hdulist->used.bzero = 1;
+ hdulist->bzero = 0.0;
+ hdulist->used.bscale = 1;
+ hdulist->bscale = 1.0;
+
+ snprintf(temp_s, FITS_CARD_SIZE, "CCD-TEMP= %g / degrees celcius", APGFrame.temperature);
+ snprintf(expose_s, FITS_CARD_SIZE, "EXPOSURE= %d / milliseconds", APGFrame.expose);
+ snprintf(binning_s, FITS_CARD_SIZE, "BINNING = '(%d x %d)'", APGFrame.binX, APGFrame.binY);
+ snprintf(pixel_s, FITS_CARD_SIZE, "PIX-SIZ = '%0.f x %0.f microns square'", cam->m_PixelXSize, cam->m_PixelYSize);
+ switch (APGFrame.frameType)
+ {
+ case LIGHT_FRAME:
+ strcpy(frame_s, "FRAME = 'Light'");
+ break;
+ case BIAS_FRAME:
+ strcpy(frame_s, "FRAME = 'Bias'");
+ break;
+ case FLAT_FRAME:
+ strcpy(frame_s, "FRAME = 'Flat Field'");
+ break;
+ case DARK_FRAME:
+ strcpy(frame_s, "FRAME = 'Dark'");
+ break;
+ }
+
+ fits_add_card (hdulist, frame_s);
+ fits_add_card (hdulist, temp_s);
+ fits_add_card (hdulist, expose_s);
+ fits_add_card (hdulist, pixel_s);
+ fits_add_card (hdulist, "INSTRUME= 'Apogee CCD'");
+ fits_add_card (hdulist, obsDate);
+
+ return (hdulist);
+}
+
+// Convert a string to a decimal or hexadecimal integer
+// Code taken from Dave Mills Apogee driver
+unsigned short ApogeeCam::hextoi(char *instr)
+{
+ unsigned short val, tot = 0;
+ bool IsHEX = false;
+
+ long n = strlen( instr );
+ if ( n > 1 )
+ { // Look for hex format e.g. 8Fh, A3H or 0x5D
+ if ( instr[ n - 1 ] == 'h' || instr[ n - 1 ] == 'H' )
+ IsHEX = true;
+ else if ( *instr == '0' && *(instr+1) == 'x' )
+ {
+ IsHEX = true;
+ instr += 2;
+ }
+ }
+
+ if ( IsHEX )
+ {
+ while (instr && *instr && isxdigit(*instr))
+ {
+ val = *instr++ - '0';
+ if (9 < val)
+ val -= 7;
+ tot <<= 4;
+ tot |= (val & 0x0f);
+ }
+ }
+ else
+ tot = atoi( instr );
+
+ return tot;
+}
+
+double ApogeeCam::min()
+{
+ double lmin = APGFrame.img[0];
+ int ind=0, i, j;
+
+ for (i= 0; i < APGFrame.height ; i++)
+ for (j= 0; j < APGFrame.width; j++)
+ {
+ ind = (i * APGFrame.width) + j;
+ if (APGFrame.img[ind] < lmin) lmin = APGFrame.img[ind];
+ }
+
+ return lmin;
+}
+
+double ApogeeCam::max()
+{
+ double lmax = APGFrame.img[0];
+ int ind=0, i, j;
+
+ for (i= 0; i < APGFrame.height ; i++)
+ for (j= 0; j < APGFrame.width; j++)
+ {
+ ind = (i * APGFrame.width) + j;
+ if (APGFrame.img[ind] > lmax) lmax = APGFrame.img[ind];
+ }
+
+ return lmax;
+}
+
diff --git a/kstars/kstars/indi/apogee_ppi.h b/kstars/kstars/indi/apogee_ppi.h
new file mode 100644
index 00000000..bed27b02
--- /dev/null
+++ b/kstars/kstars/indi/apogee_ppi.h
@@ -0,0 +1,167 @@
+#if 0
+ Apogee PPI
+ INDI Interface for Apogee PPI
+ Copyright (C) 2005 Jasem Mutlaq (mutlaqja AT ikarustech DOT com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#ifndef APOGEE_PPI_H
+#define APOGEE_PPI_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "fitsrw.h"
+#include "indidevapi.h"
+#include "eventloop.h"
+#include "indicom.h"
+#include "apogee/CameraIO_Linux.h"
+
+#define mydev "Apogee PPI"
+
+#define COMM_GROUP "Communication"
+#define EXPOSE_GROUP "Expose"
+#define IMAGE_GROUP "Image Settings"
+#define DATA_GROUP "Data Channel"
+
+#define POLLMS 1000 /* Polling time (ms) */
+#define TEMP_THRESHOLD .25 /* Differential temperature threshold (C)*/
+
+#define MAX_PIXELS 4096
+#define MAXHBIN 8
+#define MAXVBIN 64
+#define MIN_CCD_TEMP -60
+#define MAX_CCD_TEMP 40
+#define MAXCOLUMNS 16383
+#define MAXROWS 16383
+#define MAXTOTALCOLUMNS 16383
+#define MAXTOTALROWS 16383
+
+#define FILENAMESIZ 2048
+#define LIBVERSIZ 1024
+#define PREFIXSIZ 64
+#define PIPEBUFSIZ 8192
+#define FRAME_ILEN 64
+
+#define getBigEndian(p) ( ((p & 0xff) << 8) | (p >> 8))
+
+class ApogeeCam {
+
+ public:
+
+ ApogeeCam();
+ ~ApogeeCam();
+
+ /* INDI Functions that must be called from indidrivermain */
+ void ISGetProperties (const char *dev);
+ void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+ void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+ void ISPoll();
+
+ private:
+
+ /* Structs */
+ struct
+ {
+ short width;
+ short height;
+ int frameType;
+ int expose;
+ double temperature;
+ int binX, binY;
+ unsigned short *img;
+ } APGFrame;
+
+ enum { LIGHT_FRAME , BIAS_FRAME, DARK_FRAME, FLAT_FRAME };
+
+ /* Switches */
+ ISwitch PowerS[2];
+ ISwitch *ApogeeModelS;
+ ISwitch FrameTypeS[4];
+
+ /* Numbers */
+ INumber FrameN[4];
+ INumber BinningN[2];
+ INumber ExposeTimeN[1];
+ INumber TemperatureN[1];
+ INumber DataChannelN[1];
+
+ /* BLOBs */
+ IBLOB imageB;
+
+ /* Switch vectors */
+ ISwitchVectorProperty PowerSP; /* Connection switch */
+ ISwitchVectorProperty ApogeeModelSP; /* Apogee Model */
+ ISwitchVectorProperty FrameTypeSP; /* Frame type */
+
+ /* Number vectors */
+ INumberVectorProperty FrameNP; /* Frame specs */
+ INumberVectorProperty BinningNP; /* Binning */
+ INumberVectorProperty ExposeTimeNP; /* Exposure */
+ INumberVectorProperty TemperatureNP; /* Temperature control */
+
+
+ /* BLOB vectors */
+ IBLOBVectorProperty imageBP; /* Data stream */
+
+ /* Other */
+ static int streamTimerID; /* Stream ID */
+ double targetTemp; /* Target temperature */
+ CCameraIO *cam; /* Apogee Camera object */
+
+ /* Functions */
+
+ /* General */
+ void initProperties();
+ bool loadXMLModel();
+ bool initCamera();
+
+ /* CCD */
+ void getBasicData(void);
+ void handleExposure(void *);
+ void connectCCD(void);
+ void uploadFile(char * filename);
+ int writeFITS(char *filename, char errmsg[]);
+ int setImageArea(char errmsg[]);
+ void grabImage(void);
+ int isCCDConnected(void);
+
+ /* Power */
+ int checkPowerS(ISwitchVectorProperty *sp);
+ int checkPowerN(INumberVectorProperty *np);
+ int checkPowerT(ITextVectorProperty *tp);
+
+ /* Helper functions */
+ int manageDefaults(char errmsg[]);
+ int getOnSwitch(ISwitchVectorProperty *sp);
+ FITS_HDU_LIST * create_fits_header (FITS_FILE *ofp, uint width, uint height, uint bpp);
+ unsigned short hextoi(char* instr);
+ double min();
+ double max();
+
+};
+
+#endif
+
diff --git a/kstars/kstars/indi/base64.c b/kstars/kstars/indi/base64.c
new file mode 100644
index 00000000..28424512
--- /dev/null
+++ b/kstars/kstars/indi/base64.c
@@ -0,0 +1,245 @@
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02110-1301, USA.
+ *
+ * Adapted from code written by Eric S. Raymond <esr@snark.thyrsus.com>
+ *
+ */
+
+/* Pair of functions to convert to/from base64.
+ * Also can be used to build a standalone utility and a loopback test.
+ * see http://www.faqs.org/rfcs/rfc3548.html
+ */
+
+/** \file base64.c
+ \brief Pair of functions to convert to/from base64.
+
+*/
+
+#include <ctype.h>
+#include "base64.h"
+
+static const char base64digits[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+#define BAD (-1)
+static const char base64val[] = {
+ BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
+ BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
+ BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,BAD,BAD, BAD,BAD,BAD,BAD,
+ BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,BAD, BAD,BAD,BAD,BAD,
+ BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,BAD, BAD,BAD,BAD,BAD
+};
+#define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
+
+/* convert inlen raw bytes at in to base64 string (NUL-terminated) at out.
+ * out size should be at least 4*inlen/3 + 4.
+ * return length of out (sans trailing NUL).
+ */
+int
+to64frombits(unsigned char *out, const unsigned char *in, int inlen)
+{
+ unsigned char *out0 = out;
+
+ for (; inlen >= 3; inlen -= 3)
+ {
+ *out++ = base64digits[in[0] >> 2];
+ *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
+ *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
+ *out++ = base64digits[in[2] & 0x3f];
+ in += 3;
+ }
+ if (inlen > 0)
+ {
+ unsigned char fragment;
+
+ *out++ = base64digits[in[0] >> 2];
+ fragment = (in[0] << 4) & 0x30;
+ if (inlen > 1)
+ fragment |= in[1] >> 4;
+ *out++ = base64digits[fragment];
+ *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
+ *out++ = '=';
+ }
+ *out = '\0';
+
+ return (out-out0);
+}
+
+/* convert base64 at in to raw bytes out, returning count or <0 on error.
+ * base64 may contain any embedded whitespace.
+ * out should be at least 3/4 the length of in.
+ */
+int
+from64tobits(char *out, const char *in)
+{
+ int len = 0;
+ register unsigned char digit1, digit2, digit3, digit4;
+
+ do {
+ do {digit1 = *in++;} while (isspace(digit1));
+ if (DECODE64(digit1) == BAD)
+ return(-1);
+ do {digit2 = *in++;} while (isspace(digit2));
+ if (DECODE64(digit2) == BAD)
+ return(-2);
+ do {digit3 = *in++;} while (isspace(digit3));
+ if (digit3 != '=' && DECODE64(digit3) == BAD)
+ return(-3);
+ do {digit4 = *in++;} while (isspace(digit4));
+ if (digit4 != '=' && DECODE64(digit4) == BAD)
+ return(-4);
+ *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4);
+ ++len;
+ if (digit3 != '=')
+ {
+ *out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2);
+ ++len;
+ if (digit4 != '=')
+ {
+ *out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4);
+ ++len;
+ }
+ }
+ while (isspace(*in))
+ in++;
+ } while (*in && digit4 != '=');
+
+ return (len);
+}
+
+#ifdef BASE64_PROGRAM
+/* standalone program that converts to/from base64.
+ * cc -o base64 -DBASE64_PROGRAM base64.c
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void
+usage (char *me)
+{
+ fprintf (stderr, "Purpose: convert stdin to/from base64 on stdout\n");
+ fprintf (stderr, "Usage: %s {-t,-f}\n", me);
+ exit (1);
+}
+
+int
+main (int ac, char *av[])
+{
+ int to64 = 1;
+
+ /* decide whether to or from base64 */
+ if (ac == 2 && strcmp (av[1], "-f") == 0)
+ to64 = 0;
+ else if (ac != 1 && (ac != 2 || strcmp (av[1], "-t")))
+ usage (av[0]);
+
+ if (to64) {
+ unsigned char *rawin, *b64;
+ int i, n, nrawin, nb64;
+
+ /* read raw on stdin until EOF */
+ rawin = malloc(4096);
+ nrawin = 0;
+ while ((n = fread (rawin+nrawin, 1, 4096, stdin)) > 0)
+ rawin = realloc (rawin, (nrawin+=n)+4096);
+
+ /* convert to base64 */
+ b64 = malloc (4*nrawin/3+4);
+ nb64 = to64frombits(b64, rawin, nrawin);
+
+ /* pretty print */
+ for (i = 0; i < nb64; i += 72)
+ printf ("%.*s\n", 72, b64+i);
+ } else {
+ unsigned char *raw, *b64;
+ int n, nraw, nb64;
+
+ /* read base64 on stdin until EOF */
+ b64 = malloc(4096);
+ nb64 = 0;
+ while ((n = fread (b64+nb64, 1, 4096, stdin)) > 0)
+ b64 = realloc (b64, (nb64+=n)+4096);
+ b64[nb64] = '\0';
+
+ /* convert to raw */
+ raw = malloc (3*nb64/4);
+ nraw = from64tobits(raw, b64);
+ if (nraw < 0) {
+ fprintf (stderr, "base64 conversion error: %d\n", nraw);
+ return (1);
+ }
+
+ /* write */
+ fwrite (raw, 1, nraw, stdout);
+ }
+
+ return (0);
+}
+
+#endif
+
+#ifdef LOOPBACK_TEST
+/* standalone test that reads binary on stdin, converts to base64 and back,
+ * then compares. exit 0 if compares the same else 1
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main (int ac, char *av[])
+{
+ unsigned char *rawin, *b64, *rawback;
+ int n, nrawin, nrawback, nb64;
+
+ /* read raw on stdin until EOF */
+ rawin = malloc(4096);
+ nrawin = 0;
+ while ((n = fread (rawin+nrawin, 1, 4096, stdin)) > 0)
+ rawin = realloc (rawin, (nrawin+=n)+4096);
+
+ /* convert to base64 */
+ b64 = malloc (4*nrawin*3 + 4);
+ nb64 = to64frombits(b64, rawin, nrawin);
+
+ /* convert back to raw */
+ rawback = malloc (3*nb64/4);
+ nrawback = from64tobits(rawback, b64);
+ if (nrawback < 0) {
+ fprintf (stderr, "base64 error: %d\n", nrawback);
+ return(1);
+ }
+ if (nrawback != nrawin) {
+ fprintf (stderr, "base64 back length %d != %d\n", nrawback, nrawin);
+ return(1);
+ }
+
+ /* compare */
+ if (memcmp (rawback, rawin, nrawin)) {
+ fprintf (stderr, "compare error\n");
+ return (1);
+ }
+
+ /* success */
+ return (0);
+}
+#endif
+/* For RCS Only -- Do Not Edit */
+static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile$ $Date$ $Revision$ $Name: $"};
diff --git a/kstars/kstars/indi/base64.h b/kstars/kstars/indi/base64.h
new file mode 100644
index 00000000..d99e474f
--- /dev/null
+++ b/kstars/kstars/indi/base64.h
@@ -0,0 +1,36 @@
+#ifndef BASE64_H
+#define BASE64_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup base64 Functions to convert from and to base64
+ */
+/*@{*/
+
+/** \brief Convert bytes array to base64.
+ \param out output buffer in base64. The buffer size must be at least (4 * inlen / 3 + 4) bytes long.
+ \param in input binary buffer
+ \param inlen number of bytes to convert
+ \return 0 on success, -1 on failure.
+ */
+extern int to64frombits(unsigned char *out, const unsigned char *in,
+ int inlen);
+
+/** \brief Convert base64 to bytes array.
+ \param out output buffer in bytes. The buffer size must be at least (3 * size_of_in_buffer / 4) bytes long.
+ \param in input base64 buffer
+ \return 0 on success, -1 on failure.
+ */
+
+extern int from64tobits(char *out, const char *in);
+
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/kstars/kstars/indi/celestrongps.cpp b/kstars/kstars/indi/celestrongps.cpp
new file mode 100644
index 00000000..a187aaf8
--- /dev/null
+++ b/kstars/kstars/indi/celestrongps.cpp
@@ -0,0 +1,778 @@
+#if 0
+ Celestron GPS
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "celestronprotocol.h"
+#include "celestrongps.h"
+
+#define RA_THRESHOLD 0.01
+#define DEC_THRESHOLD 0.05
+#define mydev "Celestron GPS"
+
+CelestronGPS *telescope = NULL;
+
+
+/* There is _one_ binary for all LX200 drivers, but each binary is renamed
+** to its device name (i.e. lx200gps, lx200_16..etc). The main function will
+** fetch from std args the binary name and ISInit will create the apporpiate
+** device afterwards. If the binary name does not match any known devices,
+** we simply create a generic device
+*/
+extern char* me;
+
+#define COMM_GROUP "Communication"
+#define BASIC_GROUP "Main Control"
+#define MOVE_GROUP "Movement Control"
+
+static void ISPoll(void *);
+
+/*INDI controls */
+static ISwitch PowerS[] = {{"CONNECT" , "Connect" , ISS_OFF, 0, 0},{"DISCONNECT", "Disconnect", ISS_ON, 0, 0}};
+static ISwitch SlewModeS[] = {{"Slew", "", ISS_ON, 0, 0}, {"Find", "", ISS_OFF, 0, 0}, {"Centering", "", ISS_OFF, 0, 0}, {"Guide", "", ISS_OFF, 0, 0}};
+static ISwitch OnCoordSetS[] = {{"SLEW", "Slew", ISS_ON, 0 , 0}, {"TRACK", "Track", ISS_OFF, 0, 0}, {"SYNC", "Sync", ISS_OFF, 0, 0}};
+static ISwitch abortSlewS[] = {{"ABORT", "Abort", ISS_OFF, 0, 0}};
+
+static ISwitch MovementS[] = {{"N", "North", ISS_OFF, 0, 0}, {"W", "West", ISS_OFF, 0, 0}, {"E", "East", ISS_OFF, 0, 0}, {"S", "South", ISS_OFF, 0, 0}};
+
+/* equatorial position */
+static INumber eq[] = {
+ {"RA", "RA H:M:S", "%10.6m", 0., 24., 0., 0., 0, 0, 0},
+ {"DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0., 0, 0, 0},
+};
+//TODO decide appropiate TIME_OUT
+static INumberVectorProperty eqNum = {
+ mydev, "EQUATORIAL_EOD_COORD", "Equatorial JNow", BASIC_GROUP, IP_RW, 0, IPS_IDLE,
+ eq, NARRAY(eq), "", 0};
+
+/* Fundamental group */
+static ISwitchVectorProperty PowerSw = { mydev, "CONNECTION" , "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, PowerS, NARRAY(PowerS), "", 0};
+static IText PortT[] = {{"PORT", "Port", 0, 0, 0, 0}};
+static ITextVectorProperty Port = { mydev, "DEVICE_PORT", "Ports", COMM_GROUP, IP_RW, 0, IPS_IDLE, PortT, NARRAY(PortT), "", 0};
+
+/* Movement group */
+static ISwitchVectorProperty OnCoordSetSw = { mydev, "ON_COORD_SET", "On Set", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, OnCoordSetS, NARRAY(OnCoordSetS), "", 0};
+static ISwitchVectorProperty abortSlewSw = { mydev, "ABORT_MOTION", "Abort Slew/Track", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, abortSlewS, NARRAY(abortSlewS), "", 0};
+static ISwitchVectorProperty SlewModeSw = { mydev, "Slew rate", "", MOVE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, SlewModeS, NARRAY(SlewModeS), "", 0};
+
+static ISwitchVectorProperty MovementSw = { mydev, "MOVEMENT", "Move toward", MOVE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, MovementS, NARRAY(MovementS), "", 0};
+
+
+/* send client definitions of all properties */
+void ISInit()
+{
+ static int isInit=0;
+
+ if (isInit)
+ return;
+
+ isInit = 1;
+
+ PortT[0].text = strcpy(new char[32], "/dev/ttyS0");
+
+ telescope = new CelestronGPS();
+
+ IEAddTimer (POLLMS, ISPoll, NULL);
+}
+
+void ISGetProperties (const char *dev)
+{ ISInit(); telescope->ISGetProperties(dev);}
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{ ISInit(); telescope->ISNewSwitch(dev, name, states, names, n);}
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{ ISInit(); telescope->ISNewText(dev, name, texts, names, n);}
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{ ISInit(); telescope->ISNewNumber(dev, name, values, names, n);}
+void ISPoll (void *p) { telescope->ISPoll(); IEAddTimer (POLLMS, ISPoll, NULL); p=p;}
+void ISNewBLOB (const char */*dev*/, const char */*name*/, int */*sizes[]*/, char **/*blobs[]*/, char **/*formats[]*/, char **/*names[]*/, int /*n*/)
+{}
+
+/**************************************************
+*** LX200 Generic Implementation
+***************************************************/
+
+CelestronGPS::CelestronGPS()
+{
+
+ targetRA = lastRA = 0;
+ targetDEC = lastDEC = 0;
+ currentSet = 0;
+ lastSet = -1;
+ lastMove[0] = lastMove[1] = lastMove[2] = lastMove[3] = 0;
+
+ JD = 0;
+
+ // Children call parent routines, this is the default
+ IDLog("initilizaing from Celeston GPS device...\n");
+
+}
+
+void CelestronGPS::ISGetProperties(const char *dev)
+{
+
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ // COMM_GROUP
+ IDDefSwitch (&PowerSw, NULL);
+ IDDefText (&Port, NULL);
+
+ // BASIC_GROUP
+ IDDefNumber (&eqNum, NULL);
+ IDDefSwitch (&OnCoordSetSw, NULL);
+ IDDefSwitch (&abortSlewSw, NULL);
+ IDDefSwitch (&SlewModeSw, NULL);
+
+ // Movement group
+ IDDefSwitch (&MovementSw, NULL);
+
+ /* Send the basic data to the new client if the previous client(s) are already connected. */
+ if (PowerSw.s == IPS_OK)
+ getBasicData();
+
+}
+
+void CelestronGPS::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+ IText *tp;
+
+ // suppress warning
+ n=n;
+ // ignore if not ours //
+ if (strcmp (dev, mydev))
+ return;
+
+ if (!strcmp(name, Port.name) )
+ {
+ Port.s = IPS_OK;
+
+ tp = IUFindText( &Port, names[0] );
+ if (!tp)
+ return;
+
+ tp->text = new char[strlen(texts[0])+1];
+ strcpy(tp->text, texts[0]);
+ IDSetText (&Port, NULL);
+ return;
+ }
+}
+
+int CelestronGPS::handleCoordSet()
+{
+
+ int i=0;
+ char RAStr[32], DecStr[32];
+
+ switch (currentSet)
+ {
+
+ // Slew
+ case 0:
+ lastSet = 0;
+ if (eqNum.s == IPS_BUSY)
+ {
+ StopNSEW();
+ // sleep for 500 mseconds
+ usleep(500000);
+ }
+
+ if ((i = SlewToCoords(targetRA, targetDEC)))
+ {
+ slewError(i);
+ return (-1);
+ }
+
+ eqNum.s = IPS_BUSY;
+ fs_sexa(RAStr, targetRA, 2, 3600);
+ fs_sexa(DecStr, targetDEC, 2, 3600);
+ IDSetNumber(&eqNum, "Slewing to JNOW RA %s - DEC %s", RAStr, DecStr);
+ IDLog("Slewing to JNOW RA %s - DEC %s", RAStr, DecStr);
+ break;
+
+
+ // Track
+ case 1:
+ if (eqNum.s == IPS_BUSY)
+ {
+ StopNSEW();
+ // sleep for 500 mseconds
+ usleep(500000);
+ }
+
+ if ( (fabs ( targetRA - currentRA ) >= TRACKING_THRESHOLD) ||
+ (fabs (targetDEC - currentDEC) >= TRACKING_THRESHOLD))
+ {
+
+ IDLog("Exceeded Tracking threshold, will attempt to slew to the new target.\n");
+ IDLog("targetRA is %g, currentRA is %g\n", targetRA, currentRA);
+ IDLog("targetDEC is %g, currentDEC is %g\n*************************\n", targetDEC, currentDEC);
+
+ if (( i = SlewToCoords(targetRA, targetDEC)))
+ {
+ slewError(i);
+ return (-1);
+ }
+
+ fs_sexa(RAStr, targetRA, 2, 3600);
+ fs_sexa(DecStr, targetDEC, 2, 3600);
+ eqNum.s = IPS_BUSY;
+ IDSetNumber(&eqNum, "Slewing to JNow RA %s - DEC %s", RAStr, DecStr);
+ IDLog("Slewing to JNOW RA %s - DEC %s", RAStr, DecStr);
+ }
+ else
+ {
+ IDLog("Tracking called, but tracking threshold not reached yet.\n");
+ eqNum.s = IPS_OK;
+ eqNum.np[0].value = currentRA;
+ eqNum.np[1].value = currentDEC;
+ if (lastSet != 1)
+ IDSetNumber(&eqNum, "Tracking...");
+ else
+ IDSetNumber(&eqNum, NULL);
+ }
+ lastSet = 1;
+ break;
+
+ // Sync
+ case 2:
+ lastSet = 2;
+ OnCoordSetSw.s = IPS_OK;
+ SyncToCoords(targetRA, targetDEC);
+ eqNum.s = IPS_OK;
+ IDSetNumber(&eqNum, "Synchronization successful.");
+ break;
+ }
+
+ return (0);
+
+}
+
+void CelestronGPS::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ double newRA=0, newDEC=0;
+
+ // ignore if not ours //
+ if (strcmp (dev, mydev))
+ return;
+
+ struct tm *tp;
+ time_t t;
+
+ time (&t);
+ tp = gmtime (&t);
+
+ if (!strcmp (name, eqNum.name))
+ {
+ int i=0, nset=0;
+
+ if (checkPower(&eqNum))
+ return;
+
+ for (nset = i = 0; i < n; i++)
+ {
+ INumber *eqp = IUFindNumber (&eqNum, names[i]);
+ if (eqp == &eq[0])
+ {
+ newRA = values[i];
+ nset += newRA >= 0 && newRA <= 24.0;
+ } else if (eqp == &eq[1])
+ {
+ newDEC = values[i];
+ nset += newDEC >= -90.0 && newDEC <= 90.0;
+ }
+ }
+
+ if (nset == 2)
+ {
+ //eqNum.s = IPS_BUSY;
+
+ tp->tm_mon += 1;
+ tp->tm_year += 1900;
+
+ // update JD
+ JD = UTtoJD(tp);
+
+ IDLog("We recevined JNOW RA %f - DEC %f\n", newRA, newDEC);;
+ /*apparentCoord( (double) J2000, JD, &newRA, &newDEC);
+ IDLog("Processed to RA %f - DEC %f\n", newRA, newDEC);*/
+
+ //eqNum.np[0].value = values[0];
+ //eqNum.np[1].value = values[1];
+ targetRA = newRA;
+ targetDEC = newDEC;
+
+ if (MovementSw.s == IPS_BUSY)
+ {
+ for (int i=0; i < 4; i++)
+ {
+ lastMove[i] = 0;
+ MovementS[i].s = ISS_OFF;
+ }
+
+ MovementSw.s = IPS_IDLE;
+ IDSetSwitch(&MovementSw, NULL);
+ }
+
+ if (handleCoordSet())
+ {
+ eqNum.s = IPS_IDLE;
+ IDSetNumber(&eqNum, NULL);
+ }
+ }
+ else
+ {
+ eqNum.s = IPS_IDLE;
+ IDSetNumber(&eqNum, "RA or Dec missing or invalid.");
+ }
+
+ return;
+ }
+}
+
+void CelestronGPS::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+
+ int index;
+ ISwitch *swp;
+
+ // Suppress warning
+ names = names;
+
+ //IDLog("in new Switch with Device= %s and Property= %s and #%d items\n", dev, name,n);
+ //IDLog("SolarSw name is %s\n", SolarSw.name);
+
+ // ignore if not ours //
+ if (strcmp (dev, mydev))
+ return;
+
+ // FIRST Switch ALWAYS for power
+ if (!strcmp (name, PowerSw.name))
+ {
+ IUResetSwitches(&PowerSw);
+ IUUpdateSwitches(&PowerSw, states, names, n);
+ powerTelescope();
+ return;
+ }
+
+ if (!strcmp(name, OnCoordSetSw.name))
+ {
+ if (checkPower(&OnCoordSetSw))
+ return;
+
+ IUResetSwitches(&OnCoordSetSw);
+ IUUpdateSwitches(&OnCoordSetSw, states, names, n);
+ currentSet = getOnSwitch(&OnCoordSetSw);
+ }
+
+ // Abort Slew
+ if (!strcmp (name, abortSlewSw.name))
+ {
+ if (checkPower(&abortSlewSw))
+ {
+ abortSlewSw.s = IPS_IDLE;
+ IDSetSwitch(&abortSlewSw, NULL);
+ return;
+ }
+
+ IUResetSwitches(&abortSlewSw);
+ StopNSEW();
+
+ if (eqNum.s == IPS_BUSY)
+ {
+ abortSlewSw.s = IPS_OK;
+ eqNum.s = IPS_IDLE;
+ IDSetSwitch(&abortSlewSw, "Slew aborted.");
+ IDSetNumber(&eqNum, NULL);
+ }
+ else if (MovementSw.s == IPS_BUSY)
+ {
+
+ for (int i=0; i < 4; i++)
+ lastMove[i] = 0;
+
+ MovementSw.s = IPS_IDLE;
+ abortSlewSw.s = IPS_OK;
+ eqNum.s = IPS_IDLE;
+ IUResetSwitches(&MovementSw);
+ IUResetSwitches(&abortSlewSw);
+ IDSetSwitch(&abortSlewSw, "Slew aborted.");
+ IDSetSwitch(&MovementSw, NULL);
+ IDSetNumber(&eqNum, NULL);
+ }
+ else
+ {
+ IUResetSwitches(&MovementSw);
+ abortSlewSw.s = IPS_IDLE;
+ IDSetSwitch(&abortSlewSw, NULL);
+ }
+
+ return;
+ }
+
+ // Slew mode
+ if (!strcmp (name, SlewModeSw.name))
+ {
+ if (checkPower(&SlewModeSw))
+ return;
+
+ IUResetSwitches(&SlewModeSw);
+ IUUpdateSwitches(&SlewModeSw, states, names, n);
+ index = getOnSwitch(&SlewModeSw);
+ SetRate(index);
+
+ SlewModeSw.s = IPS_OK;
+ IDSetSwitch(&SlewModeSw, NULL);
+ return;
+ }
+
+ // Movement
+ if (!strcmp (name, MovementSw.name))
+ {
+ if (checkPower(&MovementSw))
+ return;
+
+ index = -1;
+ IUUpdateSwitches(&MovementSw, states, names, n);
+ swp = IUFindSwitch(&MovementSw, names[0]);
+
+ if (!swp)
+ {
+ StopNSEW();
+ IUResetSwitches(&MovementSw);
+ MovementSw.s = IPS_IDLE;
+ IDSetSwitch(&MovementSw, NULL);
+ }
+
+ if (swp == &MovementS[0]) index = 0;
+ else if (swp == &MovementS[1]) index = 1;
+ else if (swp == &MovementS[2]) index = 2;
+ else index = 3;
+
+ lastMove[index] = lastMove[index] == 0 ? 1 : 0;
+ if (lastMove[index] == 0)
+ MovementS[index].s = ISS_OFF;
+
+ // North/South movement is illegal
+ if (lastMove[NORTH] && lastMove[SOUTH])
+ {
+ StopNSEW();
+ for (int i=0; i < 4; i++)
+ lastMove[i] = 0;
+
+ IUResetSwitches(&MovementSw);
+ MovementSw.s = IPS_IDLE;
+ IDSetSwitch(&MovementSw, "Slew aborted.");
+ return;
+ }
+
+ // East/West movement is illegal
+ if (lastMove[EAST] && lastMove[WEST])
+ {
+ StopNSEW();
+ for (int i=0; i < 4; i++)
+ lastMove[i] = 0;
+
+ IUResetSwitches(&MovementSw);
+ MovementSw.s = IPS_IDLE;
+ IDSetSwitch(&MovementSw, "Slew aborted.");
+ return;
+ }
+
+ //IDLog("We have switch %d \n ", index);
+ //IDLog("NORTH: %d -- WEST: %d -- EAST: %d -- SOUTH %d\n", lastMove[0], lastMove[1], lastMove[2], lastMove[3]);
+
+ if (lastMove[index] == 1)
+ StartSlew(index);
+ else
+ StopSlew(index);
+
+ if (!lastMove[0] && !lastMove[1] && !lastMove[2] && !lastMove[3])
+ MovementSw.s = IPS_IDLE;
+
+ if (lastMove[index] == 0)
+ IDSetSwitch(&MovementSw, "Moving toward %s aborted.", Direction[index]);
+ else
+ {
+ MovementSw.s = IPS_BUSY;
+ IDSetSwitch(&MovementSw, "Moving %s...", Direction[index]);
+ }
+ return;
+ }
+
+}
+
+
+int CelestronGPS::getOnSwitch(ISwitchVectorProperty *sp)
+{
+ for (int i=0; i < sp->nsp ; i++)
+ if (sp->sp[i].s == ISS_ON)
+ return i;
+
+ return -1;
+}
+
+
+int CelestronGPS::checkPower(ISwitchVectorProperty *sp)
+{
+ if (PowerSw.s != IPS_OK)
+ {
+ if (!strcmp(sp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", sp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", sp->label);
+
+ sp->s = IPS_IDLE;
+ IDSetSwitch(sp, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int CelestronGPS::checkPower(INumberVectorProperty *np)
+{
+ if (PowerSw.s != IPS_OK)
+ {
+ if (!strcmp(np->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", np->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", np->label);
+
+ np->s = IPS_IDLE;
+ IDSetNumber(np, NULL);
+ return -1;
+ }
+ return 0;
+}
+
+int CelestronGPS::checkPower(ITextVectorProperty *tp)
+{
+
+ if (PowerSw.s != IPS_OK)
+ {
+ if (!strcmp(tp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", tp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", tp->label);
+
+ tp->s = IPS_IDLE;
+ IDSetText(tp, NULL);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+void CelestronGPS::ISPoll()
+{
+ double dx, dy;
+ double currentRA, currentDEC;
+ int status;
+
+ switch (eqNum.s)
+ {
+ case IPS_IDLE:
+ if (PowerSw.s != IPS_OK)
+ break;
+ currentRA = GetRA();
+ currentDEC = GetDec();
+
+ if ( fabs (currentRA - lastRA) > 0.01 || fabs (currentDEC - lastDEC) > 0.01)
+ {
+ eqNum.np[0].value = currentRA;
+ eqNum.np[1].value = currentDEC;
+ lastRA = currentRA;
+ lastDEC = currentDEC;
+ IDSetNumber (&eqNum, NULL);
+
+ }
+ break;
+
+ case IPS_BUSY:
+ currentRA = GetRA();
+ currentDEC = GetDec();
+ dx = targetRA - currentRA;
+ dy = targetDEC - currentDEC;
+
+ IDLog("targetRA is %f, currentRA is %f\n", (float) targetRA, (float) currentRA);
+ IDLog("targetDEC is %f, currentDEC is %f\n****************************\n", (float) targetDEC, (float) currentDEC);
+
+ eqNum.np[0].value = currentRA;
+ eqNum.np[1].value = currentDEC;
+
+ status = CheckCoords(targetRA, targetDEC);
+
+ // Wait until acknowledged or within 3.6', change as desired.
+ switch (status)
+ {
+ case 0: /* goto in progress */
+ IDSetNumber (&eqNum, NULL);
+ break;
+ case 1: /* goto complete within tolerance */
+ case 2: /* goto complete but outside tolerance */
+ currentRA = targetRA;
+ currentDEC = targetDEC;
+
+ /*apparentCoord( JD, (double) J2000, &currentRA, &currentDEC);*/
+
+ eqNum.np[0].value = currentRA;
+ eqNum.np[1].value = currentDEC;
+
+ eqNum.s = IPS_OK;
+
+ if (currentSet == 0)
+ {
+ IUResetSwitches(&OnCoordSetSw);
+ OnCoordSetSw.sp[0].s = ISS_ON;
+ IDSetNumber (&eqNum, "Slew is complete");
+ }
+ else
+ {
+ IUResetSwitches(&OnCoordSetSw);
+ OnCoordSetSw.sp[1].s = ISS_ON;
+ IDSetNumber (&eqNum, "Slew is complete. Tracking...");
+ }
+
+ IDSetSwitch (&OnCoordSetSw, NULL);
+ break;
+ }
+ break;
+
+ case IPS_OK:
+ if (PowerSw.s != IPS_OK)
+ break;
+ currentRA = GetRA();
+ currentDEC = GetDec();
+
+ if ( fabs (currentRA - lastRA) > 0.01 || fabs (currentDEC - lastDEC) > 0.01)
+ {
+
+ eqNum.np[0].value = currentRA;
+ eqNum.np[1].value = currentDEC;
+ lastRA = currentRA;
+ lastDEC = currentDEC;
+ IDSetNumber (&eqNum, NULL);
+
+ }
+ break;
+
+
+ case IPS_ALERT:
+ break;
+ }
+
+ switch (MovementSw.s)
+ {
+ case IPS_IDLE:
+ break;
+ case IPS_BUSY:
+ currentRA = GetRA();
+ currentDEC = GetDec();
+
+ /*apparentCoord( JD, (double) J2000, &currentRA, &currentDEC);*/
+
+
+ eqNum.np[0].value = currentRA;
+ eqNum.np[1].value = currentDEC;
+
+ IDSetNumber (&eqNum, NULL);
+
+ break;
+ case IPS_OK:
+ break;
+ case IPS_ALERT:
+ break;
+ }
+
+}
+
+void CelestronGPS::getBasicData()
+{
+
+ targetRA = GetRA();
+ targetDEC = GetDec();
+
+ eqNum.np[0].value = targetRA;
+ eqNum.np[1].value = targetDEC;
+
+ IDSetNumber(&eqNum, NULL);
+
+}
+
+void CelestronGPS::powerTelescope()
+{
+
+ switch (PowerSw.sp[0].s)
+ {
+ case ISS_ON:
+
+ if (ConnectTel(Port.tp[0].text) < 0)
+ {
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch (&PowerSw, "Error connecting to port %s", Port.tp[0].text);
+ return;
+ }
+
+ PowerSw.s = IPS_OK;
+ IDSetSwitch (&PowerSw, "Telescope is online. Retrieving basic data...");
+ getBasicData();
+ break;
+
+ case ISS_OFF:
+ IDSetSwitch (&PowerSw, "Telescope is offline.");
+ IDLog("Telescope is offline.");
+ DisconnectTel();
+ break;
+
+ }
+}
+
+void CelestronGPS::slewError(int slewCode)
+{
+ eqNum.s = IPS_IDLE;
+
+ switch (slewCode)
+ {
+ case 1:
+ IDSetNumber (&eqNum, "Invalid newDec in SlewToCoords");
+ break;
+ case 2:
+ IDSetNumber (&eqNum, "RA count overflow in SlewToCoords");
+ break;
+ case 3:
+ IDSetNumber (&eqNum, "Dec count overflow in SlewToCoords");
+ break;
+ case 4:
+ IDSetNumber (&eqNum, "No acknowledgement from telescope after SlewToCoords");
+ break;
+ default:
+ IDSetNumber (&eqNum, "Unknown error");
+ break;
+ }
+
+}
diff --git a/kstars/kstars/indi/celestrongps.h b/kstars/kstars/indi/celestrongps.h
new file mode 100644
index 00000000..ad1759fa
--- /dev/null
+++ b/kstars/kstars/indi/celestrongps.h
@@ -0,0 +1,68 @@
+/*
+ Celestron GPS
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef CELESTRONGPS_H
+#define CELESTRONGPS_H
+
+#include "indidevapi.h"
+#include "indicom.h"
+
+#define POLLMS 1000 /* poll period, ms */
+
+class CelestronGPS
+{
+ public:
+ CelestronGPS();
+ virtual ~CelestronGPS() {}
+
+ virtual void ISGetProperties (const char *dev);
+ virtual void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+ virtual void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ virtual void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+ virtual void ISPoll ();
+ virtual void getBasicData();
+
+ int checkPower(INumberVectorProperty *np);
+ int checkPower(ISwitchVectorProperty *sp);
+ int checkPower(ITextVectorProperty *tp);
+ void powerTelescope();
+ void slewError(int slewCode);
+ int handleCoordSet();
+ int getOnSwitch(ISwitchVectorProperty *sp);
+
+ private:
+ int timeFormat;
+
+ double JD;
+ double currentRA;
+ double currentDEC;
+ double targetRA;
+ double targetDEC;
+ double lastRA;
+ double lastDEC;
+
+ int lastSet;
+ int currentSet;
+ int lastMove[4];
+
+};
+
+#endif
+
diff --git a/kstars/kstars/indi/celestronprotocol.c b/kstars/kstars/indi/celestronprotocol.c
new file mode 100644
index 00000000..03342f71
--- /dev/null
+++ b/kstars/kstars/indi/celestronprotocol.c
@@ -0,0 +1,795 @@
+/*
+ * Telescope Control Protocol for Celestron NexStar GPS telescopes
+ *
+ * Copyright 2003 John Kielkopf
+ * John Kielkopf (kielkopf@louisville.edu)
+ *
+ * Distributed under the terms of the General Public License (see LICENSE)
+ *
+ * 15 May 2003 -- Version 2.00
+ *
+ *
+ *
+ */
+
+
+#include <stdio.h>
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <math.h>
+#include "celestronprotocol.h"
+
+#define NULL_PTR(x) (x *)0
+
+/* There are two classes of routines defined here: */
+
+/* XmTel commands to allow easy NexStar access. These */
+/* include routines that mimic the extensive LX200 command */
+/* language and, for the most part, trap calls and */
+/* respond with an error message to the console. */
+
+/* NexStar specific commands and data. */
+
+/* The NexStar command set as documented by Celestron */
+/* is very limited. This version of xmtel uses ta few */
+/* auxilliary commands which permit direct access to the motor */
+/* controllers. */
+
+
+/* XmTel compatibility commands */
+
+int ConnectTel(char *port);
+void DisconnectTel(void);
+int CheckConnectTel(void);
+
+void SetRate(int newRate);
+void SetLimits(double limitLower, double limitHigher);
+void StartSlew(int direction);
+void StopSlew(int direction);
+double GetRA(void);
+double GetDec(void);
+int SlewToCoords(double newRA, double newDec);
+int SyncToCoords(double newRA, double newDec);
+int CheckCoords(double desRA, double desDec);
+
+void StopNSEW(void);
+int SetSlewRate(void);
+
+int SyncLST(double newTime);
+int SyncLocalTime(void);
+
+void Reticle(int reticle);
+void Focus(int focus);
+void Derotator(int rotate);
+void Fan(int fan);
+
+static int TelPortFD;
+static int TelConnectFlag = 0;
+
+
+/* NexStar local data */
+
+static double returnRA; /* Last update of RA */
+static double returnDec; /* Last update of Dec */
+static int updateRA; /* Set if no RA inquiry since last update */
+static int updateDec; /* Set if no Dec inquiry since last update */
+static int slewRate; /* Rate for slew request in StartSlew */
+
+
+/* Coordinate reported by NexStar = true coordinate + offset. */
+
+static double offsetRA = 0; /* Correction to RA from NexStar */
+static double offsetDec = 0; /* Correction to Dec from NexStar */
+
+
+/* NexStar local commands */
+
+void GetRAandDec(void); /* Update RA and Dec from NexStar */
+
+
+/* Serial communication utilities */
+
+
+typedef fd_set telfds;
+
+static int readn(int fd, char *ptr, int nbytes, int sec);
+static int writen(int fd, char *ptr, int nbytes);
+static int telstat(int fd,int sec,int usec);
+
+
+int CheckConnectTel(void)
+{
+ return TelConnectFlag;
+}
+
+
+
+int ConnectTel(char *port)
+{
+ struct termios tty;
+ char returnStr[128];
+ int numRead;
+
+ fprintf(stderr, "Connecting to port: %s\n",port);
+
+ if(TelConnectFlag != 0)
+ return 0;
+
+ /* Make the connection */
+
+ TelPortFD = open(port,O_RDWR);
+ if(TelPortFD == -1)
+ return -1;
+
+ tcgetattr(TelPortFD,&tty);
+ cfsetospeed(&tty, (speed_t) B9600);
+ cfsetispeed(&tty, (speed_t) B9600);
+ tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
+ tty.c_iflag = IGNBRK;
+ tty.c_lflag = 0;
+ tty.c_oflag = 0;
+ tty.c_cflag |= CLOCAL | CREAD;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VTIME] = 5;
+ tty.c_iflag &= ~(IXON|IXOFF|IXANY);
+ tty.c_cflag &= ~(PARENB | PARODD);
+ tcsetattr(TelPortFD, TCSANOW, &tty);
+
+ /* Flush the input (read) buffer */
+
+ tcflush(TelPortFD,TCIOFLUSH);
+
+ /* Test connection */
+
+ writen(TelPortFD,"Kx",2);
+ numRead=readn(TelPortFD,returnStr,3,2);
+ returnStr[numRead] = '\0';
+
+ /* Diagnostic tests */
+
+ fprintf(stderr, "ConnectTel read %d characters: %s\n",numRead,returnStr);
+ fprintf(stderr, "TelConnectFlag set to: %d\n",TelConnectFlag);
+
+ if (numRead == 2)
+ {
+ TelConnectFlag = 1;
+ return (0);
+ }
+ else
+ return -1;
+
+
+}
+
+/* Assign and save slewRate for use in StartSlew */
+
+void SetRate(int newRate)
+{
+ if(newRate == SLEW)
+ {
+ slewRate = 9;
+ }
+ else if(newRate == FIND)
+ {
+ slewRate = 6;
+ }
+ else if(newRate == CENTER)
+ {
+ slewRate = 3;
+ }
+ else if(newRate == GUIDE)
+ {
+ slewRate = 1;
+ }
+
+}
+
+
+/* Start a slew in chosen direction at slewRate */
+/* Use auxilliary NexStar command set through the hand control computer */
+
+void StartSlew(int direction)
+{
+ char slewCmd[] = { 0x50, 0x02, 0x11, 0x24, 0x09, 0x00, 0x00, 0x00 };
+ char inputStr[2048];
+
+ if(direction == NORTH)
+ {
+ slewCmd[2] = 0x11;
+ slewCmd[3] = 0x24;
+ slewCmd[4] = slewRate;
+ }
+ else if(direction == EAST)
+ {
+ slewCmd[2] = 0x10;
+ slewCmd[3] = 0x25;
+ slewCmd[4] = slewRate;
+ }
+ else if(direction == SOUTH)
+ {
+ slewCmd[2] = 0x11;
+ slewCmd[3] = 0x25;
+ slewCmd[4] = slewRate;
+ }
+ else if(direction == WEST)
+ {
+ slewCmd[2] = 0x10;
+ slewCmd[3] = 0x24;
+ slewCmd[4] = slewRate;
+ }
+
+ writen(TelPortFD,slewCmd,8);
+
+ /* Look for '#' acknowledgement of request*/
+
+ for (;;)
+ {
+ if ( readn(TelPortFD,inputStr,1,1) )
+ {
+ if (inputStr[0] == '#') break;
+ }
+ else
+ {
+ fprintf(stderr,"No acknowledgement from telescope in StartSlew.\n");
+ }
+ }
+}
+
+
+/* Stop the slew in chosen direction */
+
+void StopSlew(int direction)
+{
+ char slewCmd[] = { 0x50, 0x02, 0x11, 0x24, 0x00, 0x00, 0x00, 0x00 };
+ char inputStr[2048];
+
+ if(direction == NORTH)
+ {
+ slewCmd[2] = 0x11;
+ slewCmd[3] = 0x24;
+ }
+ else if(direction == EAST)
+ {
+ slewCmd[2] = 0x10;
+ slewCmd[3] = 0x24;
+ }
+ else if(direction == SOUTH)
+ {
+ slewCmd[2] = 0x11;
+ slewCmd[3] = 0x24;
+ }
+ else if(direction == WEST)
+ {
+ slewCmd[2] = 0x11;
+ slewCmd[3] = 0x24;
+ }
+
+ writen(TelPortFD,slewCmd,8);
+
+ /* Look for '#' acknowledgement of request*/
+
+ for (;;)
+ {
+ if ( readn(TelPortFD,inputStr,1,1) )
+ {
+ if (inputStr[0] == '#') break;
+ }
+ else
+ {
+ fprintf(stderr,"No acknowledgement from telescope in StartSlew.\n");
+ }
+ }
+}
+
+void DisconnectTel(void)
+{
+ /* printf("DisconnectTel\n"); */
+ if(TelConnectFlag == 1)
+ close(TelPortFD);
+ TelConnectFlag = 0;
+}
+
+
+/* Test update status and return the telescope right ascension */
+/* Set updateRA flag false */
+/* Last telescope readout will be returned if no RA inquiry since then */
+/* Otherwise force a new readout */
+/* Two successive calls to GetRA will always force a new readout */
+
+double GetRA(void)
+{
+ if( updateRA != 1) GetRAandDec();
+ updateRA = 0;
+ return returnRA;
+}
+
+
+/* Test update status and return the telescope declination */
+/* Set updateDec flag false */
+/* Last telescope readout will returned if no Dec inquiry since then */
+/* Otherwise force a new readout */
+/* Two successive calls to GetDec will always force a new readout */
+
+double GetDec(void)
+{
+ if( updateDec != 1) GetRAandDec();
+ updateDec = 0;
+ return returnDec;
+}
+
+
+/* Read the telescope right ascension and declination and set update status */
+
+void GetRAandDec(void)
+{
+ char returnStr[12];
+ int countRA,countDec;
+ int numRead;
+
+ writen(TelPortFD,"E",1);
+ numRead=readn(TelPortFD,returnStr,10,1);
+ returnStr[4] = returnStr[9] = '\0';
+
+/* Diagnostic
+ *
+ * printf("GetRAandDec: %d read %x\n",numRead,returnStr);
+ *
+ */
+
+ sscanf(returnStr,"%x",&countRA);
+ sscanf(returnStr+5,"%x:",&countDec);
+ returnRA = (double) countRA;
+ returnRA = returnRA / (3. * 15. * 60. * 65536./64800.);
+ returnDec = (double) countDec;
+ returnDec = returnDec / (3. * 60. * 65536./64800.);
+
+
+/* Account for the quadrant in declination */
+
+/* 90 to 180 */
+
+ if ( (returnDec > 90.) && (returnDec <= 180.) )
+ {
+ returnDec = 180. - returnDec;
+ }
+
+
+/* 180 to 270 */
+
+ if ( (returnDec > 180.) && (returnDec <= 270.) )
+ {
+ returnDec = returnDec - 270.;
+ }
+
+
+/* 270 to 360 */
+
+ if ( (returnDec > 270.) && (returnDec <= 360.) )
+ {
+ returnDec = returnDec - 360.;
+ }
+
+
+/* Set update flags */
+
+ updateRA = 1;
+ updateDec = 1;
+
+
+/* Correct for offsets and return true coordinate */
+/* Coordinate reported by NexStar = true coordinate + offset. */
+
+ returnRA = returnRA - offsetRA;
+ returnDec = returnDec - offsetDec;
+
+}
+
+
+
+/* Reset telescope coordinates to new coordinates by adjusting offsets*/
+/* Coordinate reported by NexStar = true coordinate + offset. */
+
+int SyncToCoords(double newRA, double newDec)
+{
+ offsetRA = 0.;
+ offsetDec = 0.;
+ GetRAandDec();
+ offsetRA = returnRA - newRA;
+ offsetDec = returnDec - newDec;
+
+ return (0);
+}
+
+
+/* Slew to new coordinates */
+/* Coordinate sent to NexStar = true coordinate + offset. */
+
+int SlewToCoords(double newRA, double newDec)
+{
+ int countRA,countDec;
+ char r0,r1,r2,r3,d0,d1,d2,d3;
+ double degs, hrs;
+ char outputStr[32], inputStr[2048];
+
+ /* Add offsets */
+
+ hrs = newRA + offsetRA;
+ degs = newDec + offsetDec;
+
+ /* Convert float RA to integer count */
+
+ hrs = hrs*(3. * 15. * 60. * 65536./64800.);
+ countRA = (int) hrs;
+
+
+/* Account for the quadrant in declination */
+
+ if ( (newDec >= 0.0) && (newDec <= 90.0) )
+ {
+ degs = degs*(3. * 60. * 65536./64800.);
+ }
+ else if ( (newDec < 0.0) && (newDec >= -90.0) )
+ {
+ degs = (360. + degs)*(3. * 60. * 65536./64800.);
+ }
+ else
+ {
+ fprintf(stderr,"Invalid newDec in SlewToCoords.\n");
+ return 1;
+ }
+
+
+
+ /* Convert float Declination to integer count */
+
+ countDec = (int) degs;
+
+
+ /* Convert each integer count to four HEX characters */
+ /* Inline coding just to be fast */
+
+
+ if(countRA < 65536)
+ {
+ r0 = countRA % 16;
+ if(r0 < 10)
+ {
+ r0 = r0 + 48;
+ }
+ else
+ {
+ r0 = r0 + 55;
+ }
+ countRA = countRA/16;
+ r1 = countRA % 16;
+ if(r1 < 10)
+ {
+ r1 = r1 + 48;
+ }
+ else
+ {
+ r1 = r1 + 55;
+ }
+ countRA = countRA/16;
+ r2 = countRA % 16;
+ if(r2 < 10)
+ {
+ r2 = r2 + 48;
+ }
+ else
+ {
+ r2 = r2 + 55;
+ }
+ r3 = countRA/16;
+ if(r3 < 10)
+ {
+ r3 = r3 + 48;
+ }
+ else
+ {
+ r3 = r3 + 55;
+ }
+ }
+ else
+ {
+ printf("RA count overflow in SlewToCoords.\n");
+ return 2;
+ }
+ if(countDec < 65536)
+ {
+ d0 = countDec % 16;
+ if(d0 < 10)
+ {
+ d0 = d0 + 48;
+ }
+ else
+ {
+ d0 = d0 + 55;
+ }
+ countDec = countDec/16;
+ d1 = countDec % 16;
+ if(d1 < 10)
+ {
+ d1 = d1 + 48;
+ }
+ else
+ {
+ d1 = d1 + 55;
+ }
+ countDec = countDec/16;
+ d2 = countDec % 16;
+ if(d2 < 10)
+ {
+ d2 = d2 + 48;
+ }
+ else
+ {
+ d2 = d2 + 55;
+ }
+ d3 = countDec/16;
+ if(d3 < 10)
+ {
+ d3 = d3 + 48;
+ }
+ else
+ {
+ d3 = d3 + 55;
+ }
+ }
+ else
+ {
+ fprintf(stderr,"Dec count overflow in SlewToCoords.\n");
+ return 3;
+ }
+
+
+
+ /* Send the command and characters to the NexStar */
+
+ sprintf(outputStr,"R%c%c%c%c,%c%c%c%c",r3,r2,r1,r0,d3,d2,d1,d0);
+ writen(TelPortFD,outputStr,10);
+
+ /* Look for '#' in response */
+
+ for (;;)
+ {
+ if ( readn(TelPortFD,inputStr,1,2) )
+ {
+ if (inputStr[0] == '#') break;
+ }
+ else
+ fprintf(stderr,"No acknowledgement from telescope after SlewToCoords.\n");
+ return 4;
+ }
+ return 0;
+}
+
+
+/* Test whether the destination has been reached */
+/* With the NexStar we use the goto in progress query */
+/* Return value is */
+/* 0 -- goto in progress */
+/* 1 -- goto complete within tolerance */
+/* 2 -- goto complete but outside tolerance */
+
+int CheckCoords(double desRA, double desDec)
+{
+ double errorRA, errorDec, nowRA, nowDec;
+ char inputStr[2048];
+
+ writen(TelPortFD,"L",1);
+
+ /* Look for '0#' in response indicating goto is not in progress */
+
+ for (;;)
+ {
+ if ( readn(TelPortFD,inputStr,2,2) )
+ {
+ if ( (inputStr[0] == '0') && (inputStr[1] == '#')) break;
+ }
+ else
+ return 0;
+ }
+
+
+ nowRA=GetRA();
+ errorRA = nowRA - desRA;
+ nowDec=GetDec();
+ errorDec = nowDec - desDec;
+
+
+ /* For 6 minute of arc precision; change as needed. */
+
+ if( fabs(errorRA) > (0.1/15.) || fabs(errorDec) > 0.1)
+ return 1;
+ else
+ return 2;
+}
+
+
+/* Set lower and upper limits to protect hardware */
+
+void SetLimits(double limitLower, double limitHigher)
+{
+ limitLower = limitHigher;
+ fprintf(stderr,"NexStar does not support software limits.\n");
+}
+
+
+/* Set slew speed limited by MAXSLEWRATE */
+
+int SetSlewRate(void)
+{
+ fprintf(stderr,"NexStar does not support remote setting of slew rate.\n");
+ return 0;
+}
+
+
+
+/* Stop all slew motion */
+
+void StopNSEW(void)
+{
+ char inputStr[2048];
+
+ writen(TelPortFD,"M",1);
+
+ /* Look for '#' */
+
+ for (;;)
+ {
+ if ( readn(TelPortFD,inputStr,1,1) )
+ {
+ if (inputStr[0] == '#') break;
+ }
+ else
+ {
+ fprintf(stderr,"No acknowledgement from telescope in StopNSEW.\n");
+ }
+ }
+}
+
+
+
+/* Control the reticle function using predefined values */
+
+void Reticle(int reticle)
+{
+ reticle = reticle;
+ fprintf(stderr,"NexStar does not support remote setting of reticle.\n");
+}
+
+
+/* Control the focus using predefined values */
+
+void Focus(int focus)
+{
+ focus = focus;
+ fprintf(stderr,"NexStar does not support remote setting of focus.\n");
+}
+
+
+
+/* Control the derotator using predefined values */
+
+void Derotator(int rotate)
+
+{
+ rotate = rotate;
+ fprintf(stderr,"NexStar does not support an image derotator.\n");
+}
+
+
+/* Control the fan using predefined values */
+
+void Fan(int fan)
+
+{
+ fan = fan;
+ fprintf(stderr,"NexStar does not have a fan.\n");
+}
+
+
+/* Time synchronization utilities */
+
+/* Reset the telescope sidereal time */
+
+int SyncLST(double newTime)
+{
+ newTime = newTime;
+ fprintf(stderr,"NexStar does not support remote setting of sidereal time.\n");
+ return -1;
+}
+
+
+/* Reset the telescope local time */
+
+int SyncLocalTime()
+{
+ fprintf(stderr,"NexStar does not support remote setting of local time.\n");
+ return -1;
+}
+
+
+
+
+/* Serial port utilities */
+
+static int writen(fd, ptr, nbytes)
+int fd;
+char *ptr;
+int nbytes;
+{
+ int nleft, nwritten;
+ nleft = nbytes;
+ while (nleft > 0)
+ {
+ nwritten = write (fd, ptr, nleft);
+ if (nwritten <=0 ) break;
+ nleft -= nwritten;
+ ptr += nwritten;
+ }
+ return (nbytes - nleft);
+}
+
+static int readn(fd, ptr, nbytes, sec)
+int fd;
+char *ptr;
+int nbytes;
+int sec;
+{
+ int status;
+ int nleft, nread;
+ nleft = nbytes;
+ while (nleft > 0)
+ {
+ status = telstat(fd,sec,0);
+ if (status <= 0 ) break;
+ nread = read (fd, ptr, nleft);
+
+/* Diagnostic */
+
+/* printf("readn: %d read\n", nread); */
+
+ if (nread <= 0) break;
+ nleft -= nread;
+ ptr += nread;
+ }
+ return (nbytes - nleft);
+}
+
+/*
+ * Examines the read status of a file descriptor.
+ * The timeout (sec, usec) specifies a maximum interval to
+ * wait for data to be available in the descriptor.
+ * To effect a poll, the timeout (sec, usec) should be 0.
+ * Returns non-negative value on data available.
+ * 0 indicates that the time limit referred by timeout expired.
+ * On failure, it returns -1 and errno is set to indicate the
+ * error.
+ */
+static int telstat(fd,sec,usec)
+register int fd, sec, usec;
+{
+ int ret;
+ int width;
+ struct timeval timeout;
+ telfds readfds;
+
+ memset((char *)&readfds,0,sizeof(readfds));
+ FD_SET(fd, &readfds);
+ width = fd+1;
+ timeout.tv_sec = sec;
+ timeout.tv_usec = usec;
+ ret = select(width,&readfds,NULL_PTR(telfds),NULL_PTR(telfds),&timeout);
+ return(ret);
+}
+
diff --git a/kstars/kstars/indi/celestronprotocol.h b/kstars/kstars/indi/celestronprotocol.h
new file mode 100644
index 00000000..d7c956f7
--- /dev/null
+++ b/kstars/kstars/indi/celestronprotocol.h
@@ -0,0 +1,134 @@
+/*
+* Header File for the Telescope Control protocols for the Meade LX200
+* Author: John Kielkopf (kielkopf@louisville.edu)
+*
+* This file contains header information used in common with xmtel.
+*
+* 15 May 2003 -- Version 2.00
+*
+*/
+
+
+#ifndef CELESTRON_PROTOCOL_H
+#define CELESTRON_PROTOCOL_H
+
+/* These are user defined quantities that set the limits over which it */
+/* is safe to operate the telescope. */
+
+
+/* LOWER is the number of degrees from the zenith that you will allow. */
+/* Use 80, for example, to keep the eyepiece end out of the fork arm space */
+/* of an LX200 telescope. */
+
+#define LOWER 90.
+
+/* HIGHER is the horizon. 0 is an unobstructed horizon in every direction. */
+/* Use 10, for example, to limit sighting below 10 degrees above the horizon. */
+
+#define HIGHER 0.
+
+
+/* Set this if a slew to the north sends the telescope south. */
+
+#define REVERSE_NS 0 /* 1 for reverse; 0 for normal. */
+
+
+/* Set this for maximum slew rate allowed in degree/sec. */
+
+#define MAXSLEWRATE 4 /* 2 for safety; 4 for 16-inch; 8 otherwise. */
+
+
+
+
+/* The following parameters are used internally to set speed and direction. */
+/* Do not change these values. */
+
+
+#define SLEW 0
+#define FIND 1
+#define CENTER 2
+#define GUIDE 3
+
+#if REVERSE_NS > 0
+#define NORTH 3
+#define SOUTH 0
+#else
+#define NORTH 0
+#define SOUTH 3
+#endif
+
+#define EAST 2
+#define WEST 1
+
+/* Slew speed defines */
+
+# define SLEWRATE8 8 /* should be 8 degrees per second (not 16-inch) */
+# define SLEWRATE4 4 /* should be 4 degrees per second */
+# define SLEWRATE3 3 /* should be 3 degrees per second */
+# define SLEWRATE2 2 /* should be 2 degrees per second */
+
+/* Reticle defines */
+
+#define BRIGHTER 16 /* increase */
+#define DIMMER 8 /* decrease */
+#define BLINK0 0 /* no blinking */
+#define BLINK1 1 /* blink rate 1 */
+#define BLINK2 2 /* blink rate 2 */
+#define BLINK3 4 /* blink rate 3 */
+
+
+/* Focus defines */
+
+#define FOCUSOUT 8 /* positive voltage output */
+#define FOCUSIN 4 /* negative voltage output */
+#define FOCUSSTOP 0 /* no output */
+#define FOCUSSLOW 1 /* half voltage */
+#define FOCUSFAST 2 /* full voltage */
+
+
+/* Rotator defines */
+
+#define ROTATORON 1 /* image rotator on */
+#define ROTATOROFF 0 /* image rotator off */
+
+
+/* Fan defines */
+
+#define FANON 1 /* cooling fan on */
+#define FANOFF 0 /* cooling fan off */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ConnectTel(char *port);
+void DisconnectTel(void);
+int CheckConnectTel(void);
+
+void SetRate(int newRate);
+void SetLimits(double limitLower, double limitHigher);
+void StartSlew(int direction);
+void StopSlew(int direction);
+double GetRA(void);
+double GetDec(void);
+int SlewToCoords(double newRA, double newDec);
+int SyncToCoords(double newRA, double newDec);
+int CheckCoords(double desRA, double desDec);
+
+void StopNSEW(void);
+int SetSlewRate(void);
+
+int SyncLST(double newTime);
+int SyncLocalTime();
+
+void Reticle(int reticle);
+void Focus(int focus);
+void Derotator(int rotate);
+void Fan(int fan);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/kstars/kstars/indi/drivers.xml b/kstars/kstars/indi/drivers.xml
new file mode 100644
index 00000000..223e61c3
--- /dev/null
+++ b/kstars/kstars/indi/drivers.xml
@@ -0,0 +1,111 @@
+<ScopeDrivers>
+ <driver>lx200generic</driver>
+ <driver>lx200autostar</driver>
+ <driver>lx200classic</driver>
+ <driver>lx200gps</driver>
+ <driver>lx200_16</driver>
+ <driver>celestrongps</driver>
+ <driver>apmount</driver>
+ <driver>temma</driver>
+ <driver>skycommander</driver>
+</ScopeDrivers>
+<devGroup group="Telescopes">
+ <device label="LX200 Basic" focal_length="" aperture="">
+ <driver>lx200basic</driver>
+ <version>1.0</version>
+ </device>
+ <device label="LX200 Autostar" focal_length="" aperture="">
+ <driver>lx200autostar</driver>
+ <version>1.0</version>
+ </device>
+ <device label="LX200 Classic" focal_length="" aperture="">
+ <driver>lx200classic</driver>
+ <version>1.0</version>
+ </device>
+ <device label="LX200 GPS" focal_length="" aperture="">
+ <driver>lx200gps</driver>
+ <version>1.0</version>
+ </device>
+ <device label="LX200 16" focal_length="4064" aperture="406.4">
+ <driver>lx200_16</driver>
+ <version>1.0</version>
+ </device>
+ <device label="LX90" focal_length="2000" aperture="203.2">
+ <driver>lx200autostar</driver>
+ <version>1.0</version>
+ </device>
+ <device label="ETX125" focal_length="1900" aperture="127">
+ <driver>lx200autostar</driver>
+ <version>1.0</version>
+ </device>
+ <device label="ETX90" focal_length="1250" aperture="88.9">
+ <driver>lx200autostar</driver>
+ <version>1.0</version>
+ </device>
+ <device label="Celestron GPS" focal_length="" aperture="">
+ <driver>celestrongps</driver>
+ <version>0.9</version>
+ </device>
+ <device label="Celestron NexStar" focal_length="" aperture="">
+ <driver>celestrongps</driver>
+ <version>0.9</version>
+ </device>
+ <device label="Astro-Physics AP" focal_length="" aperture="">
+ <driver>apmount</driver>
+ <version>0.1</version>
+ </device>
+ <device label="Astro-Electronic FS-2" focal_length="" aperture="">
+ <driver>lx200generic</driver>
+ <version>0.1</version>
+ </device>
+ <device label="Losmandy Gemini" focal_length="" aperture="">
+ <driver>lx200generic</driver>
+ <version>0.1</version>
+ </device>
+ <device label="Mel Bartels" focal_length="" aperture="">
+ <driver>lx200generic</driver>
+ <version>0.1</version>
+ </device>
+ <device label="Temma Takahashi" focal_length="" aperture="">
+ <driver>temma</driver>
+ <version>0.1</version>
+ </device>
+ <device label="Sky Commander" focal_length="" aperture="">
+ <driver>skycommander</driver>
+ <version>0.1</version>
+ </device>
+ <device label="Argo Navis" focal_length="" aperture="">
+ <driver>lx200basic</driver>
+ <version>1.0</version>
+ </device>
+</devGroup>
+<devGroup group="CCDs">
+ <device label="FLI CCD">
+ <driver>fliccd</driver>
+ <version>1.0</version>
+ </device>
+ <device label="Apogee PPI">
+ <driver>apogee_ppi</driver>
+ <version>0.1</version>
+ </device>
+</devGroup>
+<devGroup group="Filter Wheels">
+ <device label="FLI Wheel">
+ <driver>fliwheel</driver>
+ <version>0.9</version>
+ </device>
+</devGroup>
+<devGroup group="Video">
+ <device label="Generic Video4Linux">
+ <driver>v4ldriver</driver>
+ <version>1.0</version>
+ </device>
+ <device label="Philips Webcam">
+ <driver>v4lphilips</driver>
+ <version>1.0</version>
+ </device>
+ <device label="Meade LPI">
+ <driver>meade_lpi</driver>
+ <version>0.1</version>
+ </device>
+</devGroup>
diff --git a/kstars/kstars/indi/eventloop.c b/kstars/kstars/indi/eventloop.c
new file mode 100644
index 00000000..8df3aca9
--- /dev/null
+++ b/kstars/kstars/indi/eventloop.c
@@ -0,0 +1,424 @@
+#if 0
+ INDI
+ Copyright (C) 2003 Elwood C. Downey
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+/* suite of functions to implement an event driven program.
+ *
+ * callbacks may be registered that are triggered when a file descriptor
+ * will not block when read;
+ *
+ * timers may be registered that will run no sooner than a specified delay from
+ * the moment they were registered;
+ *
+ * work procedures may be registered that are called when there is nothing
+ * else to do;
+ *
+ #define MAIN_TEST for a stand-alone test program.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "eventloop.h"
+
+/* info about one registered callback. */
+typedef struct {
+ int in_use; /* flag to make this record is active */
+ int fd; /* fd descriptor to watch for read */
+ void *ud; /* user's data handle */
+ CBF *fp; /* callback function */
+ int cid; /* unique id for this callback */
+} CB;
+
+/* info about one registered timer function */
+typedef struct {
+ int tgo; /* trigger time, ms from epoch */
+ void *ud; /* user's data handle */
+ TCF *fp; /* timer function */
+ int tid; /* unique id for this timer */
+} TF;
+
+/* info about one registered work procedure. */
+typedef struct {
+ int in_use; /* flag to make this record is active */
+ void *ud; /* user's data handle */
+ WPF *fp; /* work proc function function */
+ int wid; /* unique id for this work proc */
+} WP;
+
+
+static CB *cback; /* malloced list of callbacks */
+static int ncback; /* n entries in cback[] */
+static int cid; /* source of callback ids */
+
+static TF *timef; /* malloced list of timer functions */
+static int ntimef; /* n entries in ntimef[] */
+static struct timeval epoch; /* arbitrary t0 */
+static int tid; /* source of timer ids */
+#define EPDT(tp) /* ms from epoch to timeval *tp */ \
+ (((tp)->tv_sec-epoch.tv_sec)*1000 + ((tp)->tv_usec-epoch.tv_usec)/1000)
+
+static WP *wproc; /* malloced list of work procedures */
+static int nwproc; /* n entries in wproc[] */
+static int nwpinuse; /* n entries in wproc[] marked in-use */
+static int wid; /* source of worproc ids */
+
+static void runWorkProcs (void);
+static void callCallbacks(fd_set *rfdp, int nready);
+static void popTimers();
+static void oneLoop(void);
+
+/* inf loop to dispatch callbacks, work procs and timers as necessary.
+ * never returns.
+ */
+void
+eventLoop()
+{
+ /* init epoch to now */
+ gettimeofday (&epoch, NULL);
+
+ /* run loop forever */
+ while (1)
+ oneLoop();
+}
+
+/* register a new callback, fp, to be called with ud as arg when fd is ready.
+ * return a unique callback id for use with rmCallback().
+ */
+int
+addCallback (int fd, CBF *fp, void *ud)
+{
+ CB *cp;
+
+ for (cp = cback; cp < &cback[ncback]; cp++)
+ if (!cp->in_use)
+ break;
+
+ if (cp == &cback[ncback]) {
+ cback = cback ? (CB *) realloc (cback, (ncback+1)*sizeof(CB))
+ : (CB *) malloc (sizeof(CB));
+ cp = &cback[ncback++];
+ }
+
+ cp->in_use = 1;
+ cp->fp = fp;
+ cp->ud = ud;
+ cp->fd = fd;
+ return (cp->cid = ++cid);
+}
+
+/* remove the callback with the given id, as returned from addCallback().
+ * silently ignore if id not found.
+ */
+void
+rmCallback (int callbackid)
+{
+ CB *cp;
+
+ for (cp = cback; cp < &cback[ncback]; cp++) {
+ if (cp->in_use && cp->cid == callbackid) {
+ cp->in_use = 0;
+ break;
+ }
+ }
+}
+
+/* register a new timer function, fp, to be called with ud as arg after ms
+ * milliseconds. add to list in order of decreasing time from epoch, ie,
+ * last entry runs soonest. return id for use with rmTimer().
+ */
+int
+addTimer (int ms, TCF *fp, void *ud)
+{
+ struct timeval t;
+ TF *tp;
+
+ gettimeofday (&t, NULL);
+
+ timef = timef ? (TF *) realloc (timef, (ntimef+1)*sizeof(TF))
+ : (TF *) malloc (sizeof(TF));
+ tp = &timef[ntimef++];
+
+ tp->ud = ud;
+ tp->fp = fp;
+ tp->tgo = EPDT(&t) + ms;
+
+ for ( ; tp > timef && tp[0].tgo > tp[-1].tgo; tp--) {
+ TF tmptf = tp[-1];
+ tp[-1] = tp[0];
+ tp[0] = tmptf;
+ }
+
+ return (tp->tid = ++tid);
+}
+
+/* remove the timer with the given id, as returned from addTimer().
+ * silently ignore if id not found.
+ */
+void
+rmTimer (int timerID)
+{
+ TF *tp;
+
+ /* find it */
+ for (tp = timef; tp < &timef[ntimef]; tp++)
+ if (tp->tid == timerID)
+ break;
+ if (tp == &timef[ntimef])
+ return;
+
+ /* bubble it out */
+ for (++tp; tp < &timef[ntimef]; tp++)
+ tp[-1] = tp[0];
+
+ /* shrink list */
+ timef = (TF *) realloc (timef, (--ntimef)*sizeof(CB));
+}
+
+/* add a new work procedure, fp, to be called with ud when nothing else to do.
+ * return unique id for use with rmWorkProc().
+ */
+int
+addWorkProc (WPF *fp, void *ud)
+{
+ WP *wp;
+
+ for (wp = wproc; wp < &wproc[nwproc]; wp++)
+ if (!wp->in_use)
+ break;
+
+ if (wp == &wproc[nwproc]) {
+ wproc = wproc ? (WP *) realloc (wproc, (nwproc+1)*sizeof(WP))
+ : (WP *) malloc (sizeof(WP));
+ wp = &wproc[nwproc++];
+ }
+
+ wp->in_use = 1;
+ wp->fp = fp;
+ wp->ud = ud;
+ nwpinuse++;
+ return (wp->wid = ++wid);
+}
+
+
+/* remove the work proc with the given id, as returned from addWorkProc().
+ * silently ignore if id not found.
+ */
+void
+rmWorkProc (int workID)
+{
+ WP *wp;
+
+ for (wp = wproc; wp < &wproc[nwproc]; wp++) {
+ if (wp->in_use && wp->wid == workID) {
+ if (wp == &wproc[nwproc-1] && wp > wproc)
+ wproc = (WP *) realloc (wproc, (--nwproc)*sizeof(WP));
+ else
+ wp->in_use = 0;
+ nwpinuse--;
+ break;
+ }
+ }
+}
+
+/* run all registered work procedures */
+static void
+runWorkProcs ()
+{
+ WP *wp;
+
+ for (wp = wproc; wp < &wproc[nwproc]; wp++)
+ if (wp->in_use)
+ (*wp->fp) (wp->ud);
+}
+
+/* run all registered callbacks whose fd is listed in rfdp */
+static void
+callCallbacks(fd_set *rfdp, int nready)
+{
+ CB *cp;
+
+ for (cp = cback; nready > 0 && cp < &cback[ncback]; cp++) {
+ if (cp->in_use && FD_ISSET (cp->fd, rfdp)) {
+ (*cp->fp) (cp->fd, cp->ud);
+ nready--;
+ }
+ }
+}
+
+/* run all timers that are ready to pop. timef[] is sorted such in decreasing
+ * order of time from epoch to run, ie, last entry runs soonest.
+ */
+static void
+popTimers()
+{
+ struct timeval now;
+ int tgonow;
+ TF *tp;
+
+ gettimeofday (&now, NULL);
+ tgonow = EPDT (&now);
+ for (tp = &timef[ntimef-1]; tp >= timef && tp->tgo <= tgonow; tp--) {
+ (*tp->fp) (tp->ud);
+ printf ("\a\n");
+ ntimef--;
+ }
+}
+
+/* check fd's from each active callback.
+ * if any ready, call their callbacks else call each registered work procedure.
+ */
+static void
+oneLoop()
+{
+ struct timeval tv, *tvp;
+ fd_set rfd;
+ CB *cp;
+ int maxfd, ns;
+
+ /* build list of file descriptors to check */
+ FD_ZERO (&rfd);
+ maxfd = -1;
+ for (cp = cback; cp < &cback[ncback]; cp++) {
+ if (cp->in_use) {
+ FD_SET (cp->fd, &rfd);
+ if (cp->fd > maxfd)
+ maxfd = cp->fd;
+ }
+ }
+
+ /* if there are work procs
+ * set delay = 0
+ * else if there is at least one timer func
+ * set delay = time until soonest timer func expires
+ * else
+ * set delay = forever
+ */
+
+ if (nwpinuse > 0) {
+ tvp = &tv;
+ tvp->tv_sec = tvp->tv_usec = 0;
+ } else if (ntimef > 0) {
+ struct timeval now;
+ int late;
+ gettimeofday (&now, NULL);
+ late = timef[ntimef-1].tgo - EPDT (&now);
+ if (late < 0)
+ late = 0;
+ tvp = &tv;
+ tvp->tv_sec = late/1000;
+ tvp->tv_usec = 1000*(late%1000);
+ } else
+ tvp = NULL;
+
+ /* check file descriptors, dispatch callbacks or workprocs as per info*/
+ ns = select (maxfd+1, &rfd, NULL, NULL, tvp);
+ if (ns < 0) {
+ perror ("select");
+ exit(1);
+ }
+
+ /* dispatch */
+ if (ns == 0)
+ runWorkProcs();
+ else
+ callCallbacks(&rfd, ns);
+ if (ntimef > 0)
+ popTimers();
+}
+
+#if defined(MAIN_TEST)
+/* make a small stand-alone test program.
+ */
+
+#include <unistd.h>
+#include <sys/time.h>
+
+int counter;
+int mycid;
+int mywid;
+int mytid;
+
+char user_a = 'A';
+char user_b = 'B';
+
+void
+wp (void *ud)
+{
+ struct timeval tv;
+ char a = *(char *)ud;
+
+ gettimeofday (&tv, NULL);
+ printf ("workproc: %c @ %ld.%03ld counter %d\n", a, (long)tv.tv_sec,
+ (long)tv.tv_usec/1000, counter);
+}
+
+void
+to (void *ud)
+{
+ printf ("timeout %d\n", (int)ud);
+}
+
+void
+stdinCB (int fd, void *ud)
+{
+ char b = *(char *)ud;
+ char c;
+
+ if (read (fd, &c, 1) != 1)
+ exit(1);
+
+ switch (c) {
+ case '+': counter++; break;
+ case '-': counter--; break;
+
+ case 'W': mywid = addWorkProc (wp, &user_b); break;
+ case 'w': rmWorkProc (mywid); break;
+
+ case 'c': rmCallback (mycid); break;
+
+ case 't': rmTimer (mytid); break;
+ case '1': mytid = addTimer (1000, to, (void *)1); break;
+ case '2': mytid = addTimer (2000, to, (void *)2); break;
+ case '3': mytid = addTimer (3000, to, (void *)3); break;
+ case '4': mytid = addTimer (4000, to, (void *)4); break;
+ case '5': mytid = addTimer (5000, to, (void *)5); break;
+ default: return; /* silently absorb other chars like \n */
+ }
+
+ printf ("callback: %c counter is now %d\n", b, counter);
+}
+
+int
+main (int ac, char *av[])
+{
+ cid = addCallback (0, stdinCB, &user_a);
+ eventLoop();
+ exit(0);
+}
+
+#endif
+
+/* For RCS Only -- Do Not Edit */
+static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile$ $Date$ $Revision$ $Name: $"};
diff --git a/kstars/kstars/indi/eventloop.h b/kstars/kstars/indi/eventloop.h
new file mode 100644
index 00000000..c11204d9
--- /dev/null
+++ b/kstars/kstars/indi/eventloop.h
@@ -0,0 +1,110 @@
+#if 0
+ INDI
+ Copyright (C) 2003 Elwood C. Downey
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#ifndef EVENT_LOOP_H
+#define EVENT_LOOP_H
+
+/** \file eventloop.h
+ \brief Public interface to INDI's eventloop mechanism.
+ \author Elwood C. Downey
+*/
+
+/* signature of a callback, workproc and timer function */
+
+/** \typedef CBF
+ \brief Signature of a callback function.
+*/
+typedef void (CBF) (int fd, void *);
+
+/** \typedef WPF
+ \brief Signature of a work procedure function.
+*/
+typedef void (WPF) (void *);
+
+/** \typedef TCF
+ \brief Signature of a timer function.
+*/
+typedef void (TCF) (void *);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \fn void eventLoop(void)
+ \brief Main calls this when ready to hand over control.
+*/
+extern void eventLoop(void);
+
+/**
+ * \defgroup utilFunctions Utility functions to add and remove callbacks, workprocs, and timers.
+ */
+/*@{*/
+
+/** Register a new callback, \e fp, to be called with \e ud as argument when \e fd is ready.
+*
+* \param fd file descriptor.
+* \param fp a pointer to the callback function.
+* \param ud a pointer to be passed to the callback function when called.
+* \return a unique callback id for use with rmCallback().
+*/
+extern int addCallback (int fd, CBF *fp, void *ud);
+
+/** Remove a callback function.
+*
+* \param cid the callback ID returned from addCallback().
+*/
+extern void rmCallback (int cid);
+
+/** Add a new work procedure, fp, to be called with ud when nothing else to do.
+*
+* \param fp a pointer to the work procedure callback function.
+* \param ud a pointer to be passed to the callback function when called.
+* \return a unique id for use with rmWorkProc().
+*/
+extern int addWorkProc (WPF *fp, void *ud);
+
+/** Remove the work procedure with the given \e id, as returned from addWorkProc().
+*
+* \param wid the work procedure callback ID returned from addWorkProc().
+*/
+extern void rmWorkProc (int wid);
+
+/** Register a new timer function, \e fp, to be called with \e ud as argument after \e ms. Add to list in order of decreasing time from epoch, ie, last entry runs soonest. The timer will only invoke the callback function \b once. You need to call addTimer again if you want to repeat the process.
+*
+* \param ms timer period in milliseconds.
+* \param fp a pointer to the callback function.
+* \param ud a pointer to be passed to the callback function when called.
+* \return a unique id for use with rmTimer().
+*/
+extern int addTimer (int ms, TCF *fp, void *ud);
+
+/** Remove the timer with the given \e id, as returned from addTimer().
+*
+* \param tid the timer callback ID returned from addTimer().
+*/
+extern void rmTimer (int tid);
+
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/kstars/kstars/indi/fitsrw.c b/kstars/kstars/indi/fitsrw.c
new file mode 100644
index 00000000..b21622bf
--- /dev/null
+++ b/kstars/kstars/indi/fitsrw.c
@@ -0,0 +1,2092 @@
+/******************************************************************************/
+/* Peter Kirchgessner */
+/* e-mail: pkirchg@aol.com */
+/* WWW : http://members.aol.com/pkirchg */
+/******************************************************************************/
+/* #BEG-HDR */
+/* */
+/* Package : FITS reading/writing library */
+/* Modul-Name : fitsrw.c */
+/* Description : Support of reading/writing FITS-files */
+/* Function(s) : fits_new_filestruct - (local) initialize file structure*/
+/* fits_new_hdulist - (local) initialize hdulist struct*/
+/* fits_delete_filestruct - (local) delete file structure */
+/* fits_delete_recordlist - (local) delete record list */
+/* fits_delete_hdulist - (local) delete hdu list */
+/* fits_nan_32 - (local) check IEEE NaN values */
+/* fits_nan_64 - (local) check IEEE NaN values */
+/* fits_get_error - get error message */
+/* fits_set_error - (local) set error message */
+/* fits_drop_error - (local) remove an error message */
+/* fits_open - open a FITS file */
+/* fits_close - close a FITS file */
+/* fits_add_hdu - add a HDU to a FITS file */
+/* fits_add_card - add a card to the HDU */
+/* fits_print_header - print a single FITS header */
+/* fits_read_header - (local) read in FITS header */
+/* fits_write_header - write a FITS header */
+/* fits_decode_header - (local) decode a header */
+/* fits_eval_pixrange - (local) evaluate range of pixels */
+/* fits_decode_card - decode a card */
+/* fits_search_card - search a card in a record list */
+/* fits_image_info - get information about image */
+/* fits_seek_image - position to an image */
+/* fits_read_pixel - read pixel values from file */
+/* fits_to_pgmraw - convert FITS-file to PGM-file */
+/* pgmraw_to_fits - convert PGM-file to FITS-file */
+/* */
+/* Author : P. Kirchgessner */
+/* Date of Gen. : 12-Apr-97 */
+/* Last modified : 20-Dec-97 */
+/* Version : 0.11 */
+/* Compiler Opt. : */
+/* Changes : */
+/* #MOD-0001, nn, 20-Dec-97, Initialize some variables */
+/* */
+/* #END-HDR */
+/******************************************************************************/
+/* References: */
+/* - NOST, Definition of the Flexible Image Transport System (FITS), */
+/* September 29, 1995, Standard, NOST 100-1.1 */
+/* (ftp://nssdc.gsfc.nasa.gov/pub/fits/fits_standard_ps.Z) */
+/* - The FITS IMAGE Extension. A Proposal. J.D. Ponz, R.W. Thompson, */
+/* J.R. Munoz, Feb. 7, 1992 */
+/* (ftp://www.cv.nrao.edu/fits/documents/standards/image.ps.gz) */
+/* */
+/******************************************************************************/
+
+#define VERSIO 0.11
+/* Identifikation: "@(#) <product> <ver> <dd-mmm-yy>" */
+static char ident[] = "@(#) libfits.c 0.11 20-Dec-97 (%I%)";
+
+/******************************************************************************/
+/* FITS reading/writing library */
+/* Copyright (C) 1997 Peter Kirchgessner */
+/* (email: pkirchg@aol.com, WWW: http://members.aol.com/pkirchg) */
+/* The library was developed for a FITS-plug-in to GIMP, the GNU Image */
+/* Manipulation Program. But it is completely independant to that. If someone */
+/* finds it useful for other purposes, try to keep it independant from your */
+/* application. */
+/******************************************************************************/
+/* */
+/* This program is free software; you can redistribute it and/or modify */
+/* it under the terms of the GNU General Public License as published by */
+/* the Free Software Foundation; either version 2 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA. */
+/******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "fitsrw.h"
+
+
+/* Declaration of local funtions */
+
+static FITS_FILE *fits_new_filestruct (void);
+static FITS_HDU_LIST *fits_new_hdulist (void);
+static void fits_delete_filestruct (FITS_FILE *ff);
+static void fits_delete_recordlist (FITS_RECORD_LIST *rl);
+static void fits_delete_hdulist (FITS_HDU_LIST *hl);
+int fits_nan_32 (unsigned char *value);
+int fits_nan_64 (unsigned char *value);
+static void fits_set_error (const char *errmsg);
+static void fits_drop_error (void);
+static FITS_RECORD_LIST *fits_read_header (FILE *fp, int *nrec);
+static FITS_HDU_LIST *fits_decode_header (FITS_RECORD_LIST *hdr,
+ long hdr_offset, long dat_offset);
+static int fits_eval_pixrange (FILE *fp, FITS_HDU_LIST *hdu);
+
+
+/* Error handling like a FIFO */
+#define FITS_MAX_ERROR 16
+#define FITS_ERROR_LENGTH 256
+static int fits_n_error = 0;
+static char fits_error[FITS_MAX_ERROR][FITS_ERROR_LENGTH];
+
+/* What byte ordering for IEEE-format we are running on ? */
+int fits_ieee32_intel = 0;
+int fits_ieee32_motorola = 0;
+int fits_ieee64_intel = 0;
+int fits_ieee64_motorola = 0;
+
+/* Macros */
+#define FITS_RETURN(msg, val) { fits_set_error (msg); return (val); }
+#define FITS_VRETURN(msg) { fits_set_error (msg); return; }
+
+/* Get pixel values from memory. p must be an (unsigned char *) */
+#define FITS_GETBITPIX16(p,val) val = ((p[0] << 8) | (p[1]))
+#define FITS_GETBITPIX32(p,val) val = \
+ ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3])
+
+/* Get floating point values from memory. p must be an (unsigned char *). */
+/* The floating point values must directly correspond */
+/* to machine representation. Otherwise it does not work. */
+#define FITS_GETBITPIXM32(p,val) \
+ { if (fits_ieee32_intel) {unsigned char uc[4]; \
+ uc[0] = p[3]; uc[1] = p[2]; uc[2] = p[1]; uc[3] = p[0]; \
+ val = *(FITS_BITPIXM32 *)uc; } \
+ else if (fits_ieee32_motorola) { val = *(FITS_BITPIXM32 *)p; } \
+ else if (fits_ieee64_motorola) {FITS_BITPIXM64 m64; \
+ unsigned char *uc= (unsigned char *)&m64; \
+ uc[0]=p[0]; uc[1]=p[1]; uc[2]=p[2]; uc[3]=p[3]; uc[4]=uc[5]=uc[6]=uc[7]=0; \
+ val = (FITS_BITPIXM32)m64; } \
+ else if (fits_ieee64_intel) {FITS_BITPIXM64 i64; \
+ unsigned char *uc= (unsigned char *)&i64; \
+ uc[0]=uc[1]=uc[2]=uc[3]=0; uc[7]=p[0]; uc[6]=p[1]; uc[5]=p[2]; uc[4]=p[3]; \
+ val = (FITS_BITPIXM32)i64;}\
+}
+
+#define FITS_GETBITPIXM64(p,val) \
+ { if (fits_ieee64_intel) {unsigned char uc[8]; \
+ uc[0] = p[7]; uc[1] = p[6]; uc[2] = p[5]; uc[3] = p[4]; \
+ uc[4] = p[3]; uc[5] = p[2]; uc[6] = p[1]; uc[7] = p[0]; \
+ val = *(FITS_BITPIXM64 *)uc; } else val = *(FITS_BITPIXM64 *)p; }
+
+#define FITS_WRITE_BOOLCARD(fp,key,value) \
+{char card[81]; \
+ snprintf (card, sizeof( card ), "%-8.8s= %20s%50s", key, value ? "T" : "F", " "); \
+ fwrite (card, 1, 80, fp); }
+
+#define FITS_WRITE_LONGCARD(fp,key,value) \
+{char card[81]; \
+ snprintf (card, sizeof( card ), "%-8.8s= %20ld%50s", key, (long)value, " "); \
+ fwrite (card, 1, 80, fp); }
+
+#define FITS_WRITE_DOUBLECARD(fp,key,value) \
+{char card[81], dbl[21], *istr; \
+ snprintf (dbl, sizeof( dbl ), "%20f", (double)value); istr = strstr (dbl, "e"); \
+ if (istr) *istr = 'E'; \
+ snprintf (card, sizeof( card ), "%-8.8s= %20.20s%50s", key, dbl, " "); \
+ fwrite (card, 1, 80, fp); }
+
+#define FITS_WRITE_STRINGCARD(fp,key,value) \
+{char card[81]; int k;\
+ snprintf (card, sizeof( card ), "%-8.8s= \'%s", key, value); \
+ for (k = strlen (card); k < 81; k++) card[k] = ' '; \
+ k = strlen (key); if (k < 8) card[19] = '\''; else card[11+k] = '\''; \
+ fwrite (card, 1, 80, fp); }
+
+#define FITS_WRITE_CARD(fp,value) \
+{char card[81]; \
+ snprintf (card, sizeof( card ), "%-80.80s", value); \
+ fwrite (card, 1, 80, fp); }
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_new_filestruct - (local) initialize file structure */
+/* */
+/* Parameters: */
+/* -none- */
+/* */
+/* Returns a pointer to an initialized fits file structure. */
+/* On failure, a NULL-pointer is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+static FITS_FILE *fits_new_filestruct (void)
+
+{FITS_FILE *ff;
+
+ ff = (FITS_FILE *)malloc (sizeof (FITS_FILE));
+ if (ff == NULL) return (NULL);
+
+ memset ((char *)ff, 0, sizeof (*ff));
+ return (ff);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_new_hdulist - (local) initialize hdulist structure */
+/* */
+/* Parameters: */
+/* -none- */
+/* */
+/* Returns a pointer to an initialized hdulist structure. */
+/* On failure, a NULL-pointer is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+static FITS_HDU_LIST *fits_new_hdulist (void)
+
+{FITS_HDU_LIST *hdl;
+
+ hdl = (FITS_HDU_LIST *)malloc (sizeof (FITS_HDU_LIST));
+ if (hdl == NULL) return (NULL);
+
+ memset ((char *)hdl, 0, sizeof (*hdl));
+ hdl->pixmin = hdl->pixmax = hdl->datamin = hdl->datamax = 0.0;
+ hdl->bzero = hdl->bscale = 0.0;
+
+ return (hdl);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_delete_filestruct - (local) delete file structure */
+/* */
+/* Parameters: */
+/* FITS_FILE *ff [I] : pointer to fits file structure */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* Frees all memory allocated by the file structure. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+static void fits_delete_filestruct (FITS_FILE *ff)
+
+{
+ if (ff == NULL) return;
+
+ fits_delete_hdulist (ff->hdu_list);
+ ff->hdu_list = NULL;
+
+ ff->fp = NULL;
+ free ((char *)ff);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_delete_recordlist - (local) delete record list */
+/* */
+/* Parameters: */
+/* FITS_RECORD_LIST *rl [I] : record list to delete */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+static void fits_delete_recordlist (FITS_RECORD_LIST *rl)
+
+{FITS_RECORD_LIST *next;
+
+ while (rl != NULL)
+ {
+ next = rl->next_record;
+ rl->next_record = NULL;
+ free ((char *)rl);
+ rl = next;
+ }
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_delete_hdulist - (local) delete hdu list */
+/* */
+/* Parameters: */
+/* FITS_HDU_LIST *hl [I] : hdu list to delete */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+static void fits_delete_hdulist (FITS_HDU_LIST *hl)
+
+{FITS_HDU_LIST *next;
+
+ while (hl != NULL)
+ {
+ fits_delete_recordlist (hl->header_record_list);
+ next = hl->next_hdu;
+ hl->next_hdu = NULL;
+ free ((char *)hl);
+ hl = next;
+ }
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_nan_32 - (local) check for IEEE NaN values (32 bit) */
+/* */
+/* Parameters: */
+/* unsigned char *v [I] : value to check */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* The function returns 1 if the value is a NaN. Otherwise 0 is returned. */
+/* The byte sequence at v must start with the sign/eponent byte. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+int fits_nan_32 (unsigned char *v)
+
+{register unsigned long k;
+
+ k = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
+ k &= 0x7fffffff; /* Dont care about the sign bit */
+
+ /* See NOST Definition of the Flexible Image Transport System (FITS), */
+ /* Appendix F, IEEE special formats. */
+ return ( ((k >= 0x7f7fffff) && (k <= 0x7fffffff))
+ || ((k >= 0x00000001) && (k <= 0x00800000)));
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_nan_64 - (local) check for IEEE NaN values (64 bit) */
+/* */
+/* Parameters: */
+/* unsigned char *v [I] : value to check */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* The function returns 1 if the value is a NaN. Otherwise 0 is returned. */
+/* The byte sequence at v must start with the sign/eponent byte. */
+/* (currently we ignore the low order 4 bytes of the mantissa. Therefore */
+/* this function is the same as for 32 bits). */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+int fits_nan_64 (unsigned char *v)
+
+{register unsigned long k;
+
+ k = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
+ k &= 0x7fffffff; /* Dont care about the sign bit */
+
+ /* See NOST Definition of the Flexible Image Transport System (FITS), */
+ /* Appendix F, IEEE special formats. */
+ return ( ((k >= 0x7f7fffff) && (k <= 0x7fffffff))
+ || ((k >= 0x00000001) && (k <= 0x00800000)));
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_get_error - get an error message */
+/* */
+/* Parameters: */
+/* -none- */
+/* */
+/* If an error message has been set, a pointer to the message is returned. */
+/* Otherwise a NULL pointer is returned. */
+/* An inquired error message is removed from the error FIFO. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+char *fits_get_error (void)
+
+{static char errmsg[FITS_ERROR_LENGTH];
+ int k;
+
+ if (fits_n_error <= 0) return (NULL);
+ strcpy (errmsg, fits_error[0]);
+
+ for (k = 1; k < fits_n_error; k++)
+ strcpy (fits_error[k-1], fits_error[k]);
+
+ fits_n_error--;
+
+ return (errmsg);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_set_error - (local) set an error message */
+/* */
+/* Parameters: */
+/* char *errmsg [I] : Error message to set */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* Places the error message in the FIFO. If the FIFO is full, */
+/* the message is discarded. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+static void fits_set_error (const char *errmsg)
+
+{
+ if (fits_n_error < FITS_MAX_ERROR)
+ {
+ strncpy (fits_error[fits_n_error], errmsg, FITS_ERROR_LENGTH);
+ fits_error[fits_n_error++][FITS_ERROR_LENGTH-1] = '\0';
+ }
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_drop_error - (local) remove an error message */
+/* */
+/* Parameters: */
+/* -none- */
+/* */
+/* Removes the last error message from the error message FIFO */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+static void fits_drop_error (void)
+
+{
+ if (fits_n_error > 0) fits_n_error--;
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_open - open a FITS file */
+/* */
+/* Parameters: */
+/* char *filename [I] : name of file to open */
+/* char *openmode [I] : mode to open the file ("r", "w") */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* On success, a FITS_FILE-pointer is returned. On failure, a NULL- */
+/* pointer is returned. */
+/* The functions scans through the file loading each header and analyzing */
+/* them. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+
+FITS_FILE *fits_open (const char* filename, const char *openmode)
+
+{int reading, writing, n_rec, n_hdr;
+ long fpos_header, fpos_data;
+ FILE *fp;
+ FITS_FILE *ff;
+ FITS_RECORD_LIST *hdrlist;
+ FITS_HDU_LIST *hdulist, *last_hdulist;
+
+ if ((filename == NULL) || (*filename == '\0') || (openmode == NULL))
+ FITS_RETURN ("fits_open: Invalid parameters", NULL);
+
+ /* initialize */
+ hdulist = NULL;
+ last_hdulist = NULL;
+
+ /* Check the IEEE-format we are running on */
+ {float one32 = 1.0;
+ double one64 = 1.0;
+ unsigned char *op32 = (unsigned char *)&one32;
+ unsigned char *op64 = (unsigned char *)&one64;
+
+ if (sizeof (float) == 4)
+ {
+ fits_ieee32_intel = (op32[3] == 0x3f);
+ fits_ieee32_motorola = (op32[0] == 0x3f);
+ }
+ if (sizeof (double) == 8)
+ {
+ fits_ieee64_intel = (op64[7] == 0x3f);
+ fits_ieee64_motorola = (op64[0] == 0x3f);
+ }
+ }
+
+ reading = (strcmp (openmode, "r") == 0);
+ writing = (strcmp (openmode, "w") == 0);
+ if ((!reading) && (!writing))
+ FITS_RETURN ("fits_open: Invalid openmode", NULL);
+
+ fp = fopen (filename, reading ? "rb" : "wb");
+ if (fp == NULL) FITS_RETURN ("fits_open: fopen() failed", NULL);
+
+ ff = fits_new_filestruct ();
+ if (ff == NULL)
+ {
+ fclose (fp);
+ FITS_RETURN ("fits_open: No more memory", NULL);
+ }
+
+ ff->fp = fp;
+ ff->openmode = *openmode;
+
+ if (writing) return (ff);
+
+ for (n_hdr = 0; ; n_hdr++) /* Read through all HDUs */
+ {
+ fpos_header = ftell (fp); /* Save file position of header */
+ hdrlist = fits_read_header (fp, &n_rec);
+
+ if (hdrlist == NULL)
+ {
+ if (n_hdr > 0) /* At least one header must be present. */
+ fits_drop_error (); /* If we got a header already, drop the error */
+ break;
+ }
+ fpos_data = ftell (fp); /* Save file position of data */
+
+ /* Decode the header */
+ hdulist = fits_decode_header (hdrlist, fpos_header, fpos_data);
+ if (hdulist == NULL)
+ {
+ fits_delete_recordlist (hdrlist);
+ break;
+ }
+ ff->n_hdu++;
+ ff->n_pic += hdulist->numpic;
+
+ if (hdulist->used.blank_value) ff->blank_used = 1;
+ if (hdulist->used.nan_value) ff->nan_used = 1;
+
+ if (n_hdr == 0)
+ ff->hdu_list = hdulist;
+ else
+ last_hdulist->next_hdu = hdulist;
+ last_hdulist = hdulist;
+ /* Evaluate the range of pixel data */
+ fits_eval_pixrange (fp, hdulist);
+
+ /* Reposition to start of next header */
+ if (fseek (fp, hdulist->data_offset+hdulist->data_size, SEEK_SET) < 0)
+ break;
+ }
+
+ return (ff);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_close - close a FITS file */
+/* */
+/* Parameters: */
+/* FITS_FILE *ff [I] : FITS file pointer */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+void fits_close (FITS_FILE *ff)
+
+{
+ if (ff == NULL) FITS_VRETURN ("fits_close: Invalid parameter");
+
+ fclose (ff->fp);
+
+ fits_delete_filestruct (ff);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_add_hdu - add a HDU to the file */
+/* */
+/* Parameters: */
+/* FITS_FILE *ff [I] : FITS file pointer */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* Adds a new HDU to the list kept in ff. A pointer to the new HDU is */
+/* returned. On failure, a NULL-pointer is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+FITS_HDU_LIST *fits_add_hdu (FITS_FILE *ff)
+
+{FITS_HDU_LIST *newhdu, *hdu;
+
+ if (ff->openmode != 'w')
+ FITS_RETURN ("fits_add_hdu: file not open for writing", NULL);
+
+ newhdu = fits_new_hdulist ();
+ if (newhdu == NULL) return (NULL);
+
+ if (ff->hdu_list == NULL)
+ {
+ ff->hdu_list = newhdu;
+ }
+ else
+ {
+ hdu = ff->hdu_list;
+ while (hdu->next_hdu != NULL)
+ hdu = hdu->next_hdu;
+ hdu->next_hdu = newhdu;
+ }
+
+ return (newhdu);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_add_card - add a card to the HDU */
+/* */
+/* Parameters: */
+/* FITS_HDU_LIST *hdulist [I] : HDU listr */
+/* char *card [I] : card to add */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* The card must follow the standards of FITS. The card must not use a */
+/* keyword that is written using *hdulist itself. On success 0 is returned. */
+/* On failure -1 is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+int fits_add_card (FITS_HDU_LIST *hdulist, char *card)
+
+{int k;
+
+ if (hdulist->naddcards >= FITS_NADD_CARDS) return (-1);
+
+ k = strlen (card);
+ if (k < FITS_CARD_SIZE)
+ {
+ memset (&(hdulist->addcards[hdulist->naddcards][k]), ' ', FITS_CARD_SIZE-k);
+ memcpy (hdulist->addcards[(hdulist->naddcards)++], card, k);
+ }
+ else
+ {
+ memcpy (hdulist->addcards[(hdulist->naddcards)++], card, FITS_CARD_SIZE);
+ }
+ return (0);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_print_header - print the internal representation */
+/* of a single header */
+/* Parameters: */
+/* FITS_HDU_LIST *hdr [I] : pointer to the header */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+void fits_print_header (FITS_HDU_LIST *hdr)
+
+{int k;
+
+ if (hdr->used.simple)
+ printf ("Content of SIMPLE-header:\n");
+ else
+ printf ("Content of XTENSION-header %s:\n", hdr->xtension);
+ printf ("header_offset : %ld\n", hdr->header_offset);
+ printf ("data_offset : %ld\n", hdr->data_offset);
+ printf ("data_size : %ld\n", hdr->data_size);
+ printf ("used data_size: %ld\n", hdr->udata_size);
+ printf ("bytes p.pixel : %d\n", hdr->bpp);
+ printf ("pixmin : %f\n", hdr->pixmin);
+ printf ("pixmax : %f\n", hdr->pixmax);
+
+ printf ("naxis : %d\n", hdr->naxis);
+ for (k = 1; k <= hdr->naxis; k++)
+ printf ("naxis%-3d : %d\n", k, hdr->naxisn[k-1]);
+
+ printf ("bitpix : %d\n", hdr->bitpix);
+
+ if (hdr->used.blank)
+ printf ("blank : %ld\n", hdr->blank);
+ else
+ printf ("blank : not used\n");
+
+ if (hdr->used.datamin)
+ printf ("datamin : %f\n", hdr->datamin);
+ else
+ printf ("datamin : not used\n");
+ if (hdr->used.datamax)
+ printf ("datamax : %f\n", hdr->datamax);
+ else
+ printf ("datamax : not used\n");
+
+ if (hdr->used.gcount)
+ printf ("gcount : %ld\n", hdr->gcount);
+ else
+ printf ("gcount : not used\n");
+ if (hdr->used.pcount)
+ printf ("pcount : %ld\n", hdr->pcount);
+ else
+ printf ("pcount : not used\n");
+
+ if (hdr->used.bscale)
+ printf ("bscale : %f\n", hdr->bscale);
+ else
+ printf ("bscale : not used\n");
+ if (hdr->used.bzero)
+ printf ("bzero : %f\n", hdr->bzero);
+ else
+ printf ("bzero : not used\n");
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_read_header - (local) read FITS header */
+/* */
+/* Parameters: */
+/* FILE *fp [I] : file pointer */
+/* int *nrec [O] : number of records read */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* Reads in all header records up to the record that keeps the END-card. */
+/* A pointer to the record list is returned on success. */
+/* On failure, a NULL-pointer is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+static FITS_RECORD_LIST *fits_read_header (FILE *fp, int *nrec)
+
+{unsigned char record[FITS_RECORD_SIZE];
+ FITS_RECORD_LIST *start_list = NULL, *cu_record = NULL, *new_record;
+ FITS_DATA *fdat;
+ int k, simple, xtension;
+
+ *nrec = 0;
+
+ k = fread (record, 1, FITS_RECORD_SIZE, fp);
+ if (k != FITS_RECORD_SIZE)
+ FITS_RETURN ("fits_read_header: Error in read of first record", NULL);
+
+ simple = (strncmp (record, "SIMPLE ", 8) == 0);
+ xtension = (strncmp (record, "XTENSION", 8) == 0);
+ if ((!simple) && (!xtension))
+ FITS_RETURN ("fits_read_header: Missing keyword SIMPLE or XTENSION", NULL);
+
+ if (simple)
+ {
+ fdat = fits_decode_card (record, typ_fbool);
+ if (fdat && !fdat->fbool)
+ fits_set_error ("fits_read_header (warning): keyword SIMPLE does not have\
+ value T");
+ }
+
+ for (;;) /* Process all header records */
+ {
+ new_record = (FITS_RECORD_LIST *)malloc (sizeof (FITS_RECORD_LIST));
+ if (new_record == NULL)
+ {
+ fits_delete_recordlist (start_list);
+ FITS_RETURN ("fits_read_header: Not enough memory", NULL);
+ }
+ memcpy (new_record->data, record, FITS_RECORD_SIZE);
+ new_record->next_record = NULL;
+ (*nrec)++;
+
+ if (start_list == NULL) /* Add new record to the list */
+ start_list = new_record;
+ else
+ cu_record->next_record = new_record;
+
+ cu_record = new_record;
+ /* Was this the last record ? */
+ if (fits_search_card (cu_record, "END") != NULL) break;
+
+ k = fread (record, 1, FITS_RECORD_SIZE, fp);
+ if (k != FITS_RECORD_SIZE)
+ FITS_RETURN ("fits_read_header: Error in read of record", NULL);
+ }
+ return (start_list);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_write_header - write a FITS header */
+/* */
+/* Parameters: */
+/* FITS_FILE *ff [I] : FITS-file pointer */
+/* FITS_HDU_LIST [I] : pointer to header */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* Writes a header to the file. On success, 0 is returned. On failure, */
+/* -1 is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+int fits_write_header (FITS_FILE *ff, FITS_HDU_LIST *hdulist)
+
+{int numcards;
+ int r;
+
+ if (ff->openmode != 'w')
+ FITS_RETURN ("fits_write_header: file not open for writing", -1);
+
+ numcards = 0;
+
+ if (hdulist->used.simple)
+ {
+ FITS_WRITE_BOOLCARD (ff->fp, "SIMPLE", 1);
+ numcards++;
+ }
+ else if (hdulist->used.xtension)
+ {
+ FITS_WRITE_STRINGCARD (ff->fp, "XTENSION", hdulist->xtension);
+ numcards++;
+ }
+
+ FITS_WRITE_LONGCARD (ff->fp, "BITPIX", hdulist->bitpix);
+ numcards++;
+
+ FITS_WRITE_LONGCARD (ff->fp, "NAXIS", hdulist->naxis);
+ numcards++;
+
+ for (r = 0; r < hdulist->naxis; r++)
+ {char naxisn[10];
+ snprintf (naxisn, sizeof( naxisn ), "NAXIS%d", r+1);
+ FITS_WRITE_LONGCARD (ff->fp, naxisn, hdulist->naxisn[r]);
+ numcards++;
+ }
+
+ if (hdulist->used.extend)
+ {
+ FITS_WRITE_BOOLCARD (ff->fp, "EXTEND", hdulist->extend);
+ numcards++;
+ }
+
+ if (hdulist->used.groups)
+ {
+ FITS_WRITE_BOOLCARD (ff->fp, "GROUPS", hdulist->groups);
+ numcards++;
+ }
+
+ if (hdulist->used.pcount)
+ {
+ FITS_WRITE_LONGCARD (ff->fp, "PCOUNT", hdulist->pcount);
+ numcards++;
+ }
+ if (hdulist->used.gcount)
+ {
+ FITS_WRITE_LONGCARD (ff->fp, "GCOUNT", hdulist->gcount);
+ numcards++;
+ }
+
+ if (hdulist->used.bzero)
+ {
+ FITS_WRITE_DOUBLECARD (ff->fp, "BZERO", hdulist->bzero);
+ numcards++;
+ }
+ if (hdulist->used.bscale)
+ {
+ FITS_WRITE_DOUBLECARD (ff->fp, "BSCALE", hdulist->bscale);
+ numcards++;
+ }
+
+ if (hdulist->used.datamin)
+ {
+ FITS_WRITE_DOUBLECARD (ff->fp, "DATAMIN", hdulist->datamin);
+ numcards++;
+ }
+ if (hdulist->used.datamax)
+ {
+ FITS_WRITE_DOUBLECARD (ff->fp, "DATAMAX", hdulist->datamax);
+ numcards++;
+ }
+
+ if (hdulist->used.blank)
+ {
+ FITS_WRITE_LONGCARD (ff->fp, "BLANK", hdulist->blank);
+ numcards++;
+ }
+
+ /* Write additional cards */
+ if (hdulist->naddcards > 0)
+ {
+ fwrite (hdulist->addcards, FITS_CARD_SIZE, hdulist->naddcards, ff->fp);
+ numcards += hdulist->naddcards;
+ }
+
+ FITS_WRITE_CARD (ff->fp, "END");
+ numcards++;
+
+ r = (numcards*FITS_CARD_SIZE) % FITS_RECORD_SIZE;
+ if (r) /* Must the record be filled up ? */
+ {
+ while (r++ < FITS_RECORD_SIZE)
+ putc (' ', ff->fp);
+ }
+
+ return (ferror (ff->fp) ? -1 : 0);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_decode_header - (local) decode a header */
+/* */
+/* Parameters: */
+/* FITS_RECORD_LIST *hdr [I] : the header record list */
+/* long hdr_offset [I] : fileposition of header */
+/* long dat_offset [I] : fileposition of data (end of header) */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* The function decodes the mostly used data within the header and generates */
+/* a FITS_HDU_LIST-entry. On failure, a NULL-pointer is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+static FITS_HDU_LIST *fits_decode_header (FITS_RECORD_LIST *hdr,
+ long hdr_offset, long dat_offset)
+
+{FITS_HDU_LIST *hdulist;
+ FITS_DATA *fdat;
+ char errmsg[80], key[9];
+ int k, bpp, random_groups;
+ long mul_axis, data_size, bitpix_supported;
+
+#define FITS_DECODE_CARD(mhdr,mkey,mfdat,mtyp) \
+ {strcpy (key, mkey); \
+ mfdat = fits_decode_card (fits_search_card (mhdr, mkey), mtyp); \
+ if (mfdat == NULL) goto err_missing; }
+
+#define FITS_TRY_CARD(mhdr,mhdu,mkey,mvar,mtyp,unionvar) \
+ {FITS_DATA *mfdat = fits_decode_card (fits_search_card (mhdr,mkey), mtyp); \
+ mhdu->used.mvar = (mfdat != NULL); \
+ if (mhdu->used.mvar) mhdu->mvar = mfdat->unionvar; }
+
+ hdulist = fits_new_hdulist ();
+ if (hdulist == NULL)
+ FITS_RETURN ("fits_decode_header: Not enough memory", NULL);
+
+ /* Initialize the header data */
+ hdulist->header_offset = hdr_offset;
+ hdulist->data_offset = dat_offset;
+
+ hdulist->used.simple = (strncmp (hdr->data, "SIMPLE ", 8) == 0);
+ hdulist->used.xtension = (strncmp (hdr->data, "XTENSION", 8) == 0);
+ if (hdulist->used.xtension)
+ {
+ fdat = fits_decode_card (fits_search_card (hdr, "XTENSION"), typ_fstring);
+ strcpy (hdulist->xtension, fdat->fstring);
+ }
+
+ FITS_DECODE_CARD (hdr, "NAXIS", fdat, typ_flong);
+ hdulist->naxis = fdat->flong;
+
+ FITS_DECODE_CARD (hdr, "BITPIX", fdat, typ_flong);
+ bpp = hdulist->bitpix = (int)fdat->flong;
+ if ( (bpp != 8) && (bpp != 16) && (bpp != 32)
+ && (bpp != -32) && (bpp != -64))
+ {
+ strcpy (errmsg, "fits_decode_header: Invalid BITPIX-value");
+ goto err_return;
+ }
+ if (bpp < 0) bpp = -bpp;
+ bpp /= 8;
+ hdulist->bpp = bpp;
+
+ FITS_TRY_CARD (hdr, hdulist, "GCOUNT", gcount, typ_flong, flong);
+ FITS_TRY_CARD (hdr, hdulist, "PCOUNT", pcount, typ_flong, flong);
+
+ FITS_TRY_CARD (hdr, hdulist, "GROUPS", groups, typ_fbool, fbool);
+ random_groups = hdulist->used.groups && hdulist->groups;
+
+ FITS_TRY_CARD (hdr, hdulist, "EXTEND", extend, typ_fbool, fbool);
+
+ if (hdulist->used.xtension) /* Extension requires GCOUNT and PCOUNT */
+ {
+ if ((!hdulist->used.gcount) || (!hdulist->used.pcount))
+ {
+ strcpy (errmsg, "fits_decode_header: Missing GCOUNT/PCOUNT for XTENSION");
+ goto err_return;
+ }
+ }
+
+ mul_axis = 1;
+
+ /* Find all NAXISx-cards */
+ for (k = 1; k <= FITS_MAX_AXIS; k++)
+ {char naxisn[9];
+
+ snprintf (naxisn, sizeof( naxisn ), "NAXIS%-3d", k);
+ fdat = fits_decode_card (fits_search_card (hdr, naxisn), typ_flong);
+ if (fdat == NULL)
+ {
+ k--; /* Save the last NAXISk read */
+ break;
+ }
+ hdulist->naxisn[k-1] = (int)fdat->flong;
+ if (hdulist->naxisn[k-1] < 0)
+ {
+ strcpy (errmsg, "fits_decode_header: Negative value in NAXISn");
+ goto err_return;
+ }
+ if ((k == 1) && (random_groups))
+ {
+ if (hdulist->naxisn[0] != 0)
+ {
+ strcpy (errmsg, "fits_decode_header: Random groups with NAXIS1 != 0");
+ goto err_return;
+ }
+ }
+ else
+ mul_axis *= hdulist->naxisn[k-1];
+ }
+
+ if ((hdulist->naxis > 0) && (k < hdulist->naxis))
+ {
+ strcpy (errmsg, "fits_decode_card: Not enough NAXISn-cards");
+ goto err_return;
+ }
+
+ /* If we have only one dimension, just set the second to size one. */
+ /* So we dont have to check for naxis < 2 in some places. */
+ if (hdulist->naxis < 2)
+ hdulist->naxisn[1] = 1;
+ if (hdulist->naxis < 1)
+ {
+ mul_axis = 0;
+ hdulist->naxisn[0] = 1;
+ }
+
+ if (hdulist->used.xtension)
+ data_size = bpp*hdulist->gcount*(hdulist->pcount + mul_axis);
+ else
+ data_size = bpp*mul_axis;
+ hdulist->udata_size = data_size; /* Used data size without padding */
+
+ /* Datasize must be a multiple of the FITS logical record size */
+ data_size = (data_size + FITS_RECORD_SIZE - 1) / FITS_RECORD_SIZE;
+ data_size *= FITS_RECORD_SIZE;
+ hdulist->data_size = data_size;
+
+
+ FITS_TRY_CARD (hdr, hdulist, "BLANK", blank, typ_flong, flong);
+
+ FITS_TRY_CARD (hdr, hdulist, "DATAMIN", datamin, typ_fdouble, fdouble);
+ FITS_TRY_CARD (hdr, hdulist, "DATAMAX", datamax, typ_fdouble, fdouble);
+
+ FITS_TRY_CARD (hdr, hdulist, "BZERO", bzero, typ_fdouble, fdouble);
+ FITS_TRY_CARD (hdr, hdulist, "BSCALE", bscale, typ_fdouble, fdouble);
+
+ /* Evaluate number of interpretable images for this HDU */
+ hdulist->numpic = 0;
+
+ /* We must support this format */
+ bitpix_supported = (hdulist->bitpix > 0)
+ || ( (hdulist->bitpix == -64)
+ && (fits_ieee64_intel || fits_ieee64_motorola))
+ || ( (hdulist->bitpix == -32)
+ && ( fits_ieee32_intel || fits_ieee32_motorola
+ || fits_ieee64_intel || fits_ieee64_motorola));
+
+ if (bitpix_supported)
+ {
+ if (hdulist->used.simple)
+ {
+ if (hdulist->naxis > 0)
+ {
+ hdulist->numpic = 1;
+ for (k = 3; k <= hdulist->naxis; k++)
+ hdulist->numpic *= hdulist->naxisn[k-1];
+ }
+ }
+ else if ( hdulist->used.xtension
+ && (strncmp (hdulist->xtension, "IMAGE", 5) == 0))
+ {
+ if (hdulist->naxis > 0)
+ {
+ hdulist->numpic = 1;
+ for (k = 3; k <= hdulist->naxis; k++)
+ hdulist->numpic *= hdulist->naxisn[k-1];
+ }
+ }
+ }
+ else
+ {char msg[160];
+ snprintf (msg, sizeof( msg ), "fits_decode_header: IEEE floating point format required for\
+ BITPIX=%d\nis not supported on this machine", hdulist->bitpix);
+ fits_set_error (msg);
+ }
+
+ hdulist->header_record_list = hdr; /* Add header records to the list */
+ return (hdulist);
+
+err_missing:
+ snprintf (errmsg, sizeof(errmsg), "fits_decode_header: missing/invalid %.50s card", key);
+
+err_return:
+ fits_delete_hdulist (hdulist);
+ fits_set_error (errmsg);
+ return (NULL);
+
+#undef FITS_DECODE_CARD
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_eval_pixrange - (local) evaluate range of pixel data */
+/* */
+/* Parameters: */
+/* FILE *fp [I] : file pointer */
+/* FITS_HDU_LIST *hdu [I] : pointer to header */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* The Function sets the values hdu->pixmin and hdu->pixmax. On success 0 */
+/* is returned. On failure, -1 is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+static int fits_eval_pixrange (FILE *fp, FITS_HDU_LIST *hdu)
+
+{register unsigned int maxelem;
+#define FITSNPIX 4096
+ unsigned char pixdat[FITSNPIX];
+ unsigned int nelem, bpp;
+ int blank_found = 0, nan_found = 0;
+
+ if (fseek (fp, hdu->data_offset, SEEK_SET) < 0)
+ FITS_RETURN ("fits_eval_pixrange: cant position file", -1);
+
+ bpp = hdu->bpp; /* Number of bytes per pixel */
+ nelem = hdu->udata_size / bpp; /* Number of data elements */
+
+ switch (hdu->bitpix)
+ {
+ case 8: {
+ register FITS_BITPIX8 pixval;
+ register unsigned char *ptr;
+ FITS_BITPIX8 minval = 255, maxval = 0;
+ FITS_BITPIX8 blankval;
+
+ while (nelem > 0)
+ {
+ maxelem = sizeof (pixdat)/bpp;
+ if (nelem < maxelem) maxelem = nelem;
+ nelem -= maxelem;
+ if (fread ((char *)pixdat, bpp, maxelem, fp) != maxelem)
+ FITS_RETURN ("fits_eval_pixrange: error on read bitpix 8 data", -1);
+
+ ptr = pixdat;
+ if (hdu->used.blank)
+ {
+ blankval = (FITS_BITPIX8)hdu->blank;
+ while (maxelem-- > 0)
+ {
+ pixval = (FITS_BITPIX8)*(ptr++);
+ if (pixval != blankval)
+ {
+ if (pixval < minval) minval = pixval;
+ else if (pixval > maxval) maxval = pixval;
+ }
+ else blank_found = 1;
+ }
+ }
+ else
+ {
+ while (maxelem-- > 0)
+ {
+ pixval = (FITS_BITPIX8)*(ptr++);
+ if (pixval < minval) minval = pixval;
+ else if (pixval > maxval) maxval = pixval;
+ }
+ }
+ }
+ hdu->pixmin = minval;
+ hdu->pixmax = maxval;
+ break; }
+
+ case 16: {
+ register FITS_BITPIX16 pixval;
+ register unsigned char *ptr;
+ FITS_BITPIX16 minval = 0x7fff, maxval = ~0x7fff;
+
+ while (nelem > 0)
+ {
+ maxelem = sizeof (pixdat)/bpp;
+ if (nelem < maxelem) maxelem = nelem;
+ nelem -= maxelem;
+ if (fread ((char *)pixdat, bpp, maxelem, fp) != maxelem)
+ FITS_RETURN ("fits_eval_pixrange: error on read bitpix 16 data", -1);
+
+ ptr = pixdat;
+ if (hdu->used.blank)
+ {FITS_BITPIX16 blankval = (FITS_BITPIX16)hdu->blank;
+
+ while (maxelem-- > 0)
+ {
+ FITS_GETBITPIX16 (ptr, pixval);
+ ptr += 2;
+ if (pixval != blankval)
+ {
+ if (pixval < minval) minval = pixval;
+ else if (pixval > maxval) maxval = pixval;
+ }
+ else blank_found = 1;
+ }
+ }
+ else
+ {
+ while (maxelem-- > 0)
+ {
+ FITS_GETBITPIX16 (ptr, pixval);
+ ptr += 2;
+ if (pixval < minval) minval = pixval;
+ else if (pixval > maxval) maxval = pixval;
+ }
+ }
+ }
+ hdu->pixmin = minval;
+ hdu->pixmax = maxval;
+ break; }
+
+
+ case 32: {
+ register FITS_BITPIX32 pixval;
+ register unsigned char *ptr;
+ FITS_BITPIX32 minval = 0x7fffffff, maxval = ~0x7fffffff;
+
+ while (nelem > 0)
+ {
+ maxelem = sizeof (pixdat)/bpp;
+ if (nelem < maxelem) maxelem = nelem;
+ nelem -= maxelem;
+ if (fread ((char *)pixdat, bpp, maxelem, fp) != maxelem)
+ FITS_RETURN ("fits_eval_pixrange: error on read bitpix 32 data", -1);
+
+ ptr = pixdat;
+ if (hdu->used.blank)
+ {FITS_BITPIX32 blankval = (FITS_BITPIX32)hdu->blank;
+
+ while (maxelem-- > 0)
+ {
+ FITS_GETBITPIX32 (ptr, pixval);
+ ptr += 4;
+ if (pixval != blankval)
+ {
+ if (pixval < minval) minval = pixval;
+ else if (pixval > maxval) maxval = pixval;
+ }
+ else blank_found = 1;
+ }
+ }
+ else
+ {
+ while (maxelem-- > 0)
+ {
+ FITS_GETBITPIX32 (ptr, pixval);
+ ptr += 4;
+ if (pixval < minval) minval = pixval;
+ else if (pixval > maxval) maxval = pixval;
+ }
+ }
+ }
+ hdu->pixmin = minval;
+ hdu->pixmax = maxval;
+ break; }
+
+ case -32: {
+ register FITS_BITPIXM32 pixval;
+ register unsigned char *ptr;
+ FITS_BITPIXM32 minval, maxval;
+ int first = 1;
+
+ /* initialize */
+
+ pixval = 0;
+ minval = 0;
+ maxval = 0;
+
+ while (nelem > 0)
+ {
+ maxelem = sizeof (pixdat)/bpp;
+ if (nelem < maxelem) maxelem = nelem;
+ nelem -= maxelem;
+ if (fread ((char *)pixdat, bpp, maxelem, fp) != maxelem)
+ FITS_RETURN ("fits_eval_pixrange: error on read bitpix -32 data", -1);
+
+ ptr = pixdat;
+ while (maxelem-- > 0)
+ {
+ if (!fits_nan_32 (ptr))
+ {
+ FITS_GETBITPIXM32 (ptr, pixval);
+ ptr += 4;
+ if (first)
+ {
+ first = 0;
+ minval = maxval = pixval;
+ }
+ else if (pixval < minval) { minval = pixval; }
+ else if (pixval > maxval) { maxval = pixval; }
+ }
+ else nan_found = 1;
+ }
+ }
+ hdu->pixmin = minval;
+ hdu->pixmax = maxval;
+ break; }
+
+ case -64: {
+ register FITS_BITPIXM64 pixval;
+ register unsigned char *ptr;
+ FITS_BITPIXM64 minval, maxval;
+ int first = 1;
+
+ /* initialize */
+
+ minval = 0;
+ maxval = 0;
+
+ while (nelem > 0)
+ {
+ maxelem = sizeof (pixdat)/bpp;
+ if (nelem < maxelem) maxelem = nelem;
+ nelem -= maxelem;
+ if (fread ((char *)pixdat, bpp, maxelem, fp) != maxelem)
+ FITS_RETURN ("fits_eval_pixrange: error on read bitpix -64 data", -1);
+
+ ptr = pixdat;
+ while (maxelem-- > 0)
+ {
+ if (!fits_nan_64 (ptr))
+ {
+ FITS_GETBITPIXM64 (ptr, pixval);
+ ptr += 8;
+ if (first)
+ {
+ first = 0;
+ minval = maxval = pixval;
+ }
+ else if (pixval < minval) { minval = pixval; }
+ else if (pixval > maxval) { maxval = pixval; }
+ }
+ else nan_found = 1;
+ }
+ }
+ hdu->pixmin = minval;
+ hdu->pixmax = maxval;
+ break; }
+ }
+ if (nan_found) hdu->used.nan_value = 1;
+ if (blank_found) hdu->used.blank_value = 1;
+
+ return (0);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_decode_card - decode a card */
+/* */
+/* Parameters: */
+/* const char *card [I] : pointer to card image */
+/* FITS_DATA_TYPES data_type [I] : datatype to decode */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* Decodes a card and returns a pointer to the union, keeping the data. */
+/* If card is NULL or on failure, a NULL-pointer is returned. */
+/* If the card does not have the value indicator, an error is generated, */
+/* but its tried to decode the card. The data is only valid up to the next */
+/* call of the function. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+FITS_DATA *fits_decode_card (const char *card, FITS_DATA_TYPES data_type)
+
+{static FITS_DATA data;
+ long l_long;
+ double l_double;
+ char l_card[FITS_CARD_SIZE+1], msg[256];
+ char *cp = ident, *dst, *end;
+
+ if (card == NULL) return (NULL);
+
+ memcpy (l_card, card, FITS_CARD_SIZE);
+ l_card[FITS_CARD_SIZE] = '\0';
+
+ if (strncmp (card+8, "= ", 2) != 0)
+ {
+ snprintf (msg, sizeof( msg ), "fits_decode_card (warning): Missing value indicator\
+ '= ' for %8.8s", l_card);
+ fits_set_error (msg);
+ }
+
+ switch (data_type)
+ {
+ case typ_bitpix8:
+ data.bitpix8 = (FITS_BITPIX8)(l_card[10]);
+ break;
+
+ case typ_bitpix16:
+ if (sscanf (l_card+10, "%ld", &l_long) != 1)
+ FITS_RETURN ("fits_decode_card: error decoding typ_bitpix16", NULL);
+ data.bitpix16 = (FITS_BITPIX16)l_long;
+ break;
+
+ case typ_bitpix32:
+ if (sscanf (l_card+10, "%ld", &l_long) != 1)
+ FITS_RETURN ("fits_decode_card: error decoding typ_bitpix32", NULL);
+ data.bitpix32 = (FITS_BITPIX32)l_long;
+ break;
+
+ case typ_bitpixm32:
+ if (sscanf (l_card+10, "%lf", &l_double) != 1)
+ FITS_RETURN ("fits_decode_card: error decoding typ_bitpixm32", NULL);
+ data.bitpixm32 = (FITS_BITPIXM32)l_double;
+ break;
+
+ case typ_bitpixm64:
+ if (sscanf (l_card+10, "%lf", &l_double) != 1)
+ FITS_RETURN ("fits_decode_card: error decoding typ_bitpixm64", NULL);
+ data.bitpixm64 = (FITS_BITPIXM64)l_double;
+ break;
+
+ case typ_fbool:
+ cp = l_card+10;
+ while (*cp == ' ') cp++;
+ if (*cp == 'T') data.fbool = 1;
+ else if (*cp == 'F') data.fbool = 0;
+ else FITS_RETURN ("fits_decode_card: error decoding typ_fbool", NULL);
+ break;
+
+ case typ_flong:
+ if (sscanf (l_card+10, "%ld", &l_long) != 1)
+ FITS_RETURN ("fits_decode_card: error decoding typ_flong", NULL);
+ data.flong = (FITS_BITPIX32)l_long;
+ break;
+
+ case typ_fdouble:
+ if (sscanf (l_card+10, "%lf", &l_double) != 1)
+ FITS_RETURN ("fits_decode_card: error decoding typ_fdouble", NULL);
+ data.fdouble = (FITS_BITPIXM32)l_double;
+ break;
+
+ case typ_fstring:
+ cp = l_card+10;
+ if (*cp != '\'')
+ FITS_RETURN ("fits_decode_card: missing \' decoding typ_fstring", NULL);
+
+ dst = data.fstring;
+ cp++;
+ end = l_card+FITS_CARD_SIZE-1;
+ for (;;) /* Search for trailing quote */
+ {
+ if (*cp != '\'') /* All characters but quote are used. */
+ {
+ *(dst++) = *cp;
+ }
+ else /* Maybe there is a quote in the string */
+ {
+ if (cp >= end) break; /* End of card ? finished */
+ if (*(cp+1) != '\'') break;
+ *(dst++) = *(cp++);
+ }
+ if (cp >= end) break;
+ cp++;
+ }
+ *dst = '\0';
+ break;
+ }
+ return (&data);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_search_card - search a card in the record list */
+/* */
+/* Parameters: */
+/* FITS_RECORD_LIST *rl [I] : record list to search */
+/* char *keyword [I] : keyword identifying the card */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* A card is searched in the reord list. Only the first eight characters of */
+/* keyword are significant. If keyword is less than 8 characters, its filled */
+/* with blanks. */
+/* If the card is found, a pointer to the card is returned. */
+/* The pointer does not point to a null-terminated string. Only the next */
+/* 80 bytes are allowed to be read. */
+/* On failure a NULL-pointer is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+char *fits_search_card (FITS_RECORD_LIST *rl, const char *keyword)
+
+{int key_len, k;
+ char *card;
+ char key[9];
+
+ key_len = strlen (keyword);
+ if (key_len > 8) key_len = 8;
+ if (key_len == 0)
+ FITS_RETURN ("fits_search_card: Invalid parameter", NULL);
+
+ strcpy (key, " ");
+ memcpy (key, keyword, key_len);
+
+ while (rl != NULL)
+ {
+ card = (char *)rl->data;
+ for (k = 0; k < FITS_RECORD_SIZE / FITS_CARD_SIZE; k++)
+ {
+ if (strncmp (card, key, 8) == 0) return (card);
+ card += FITS_CARD_SIZE;
+ }
+ rl = rl->next_record;
+ }
+ return (NULL);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_image_info - get information about an image */
+/* */
+/* Parameters: */
+/* FITS_FILE *ff [I] : FITS file structure */
+/* int picind [I] : Index of picture in file (1,2,...) */
+/* int *hdupicind [O] : Index of picture in HDU (1,2,...) */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* The function returns on success a pointer to a FITS_HDU_LIST. hdupicind */
+/* then gives the index of the image within the HDU. */
+/* On failure, NULL is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+FITS_HDU_LIST *fits_image_info (FITS_FILE *ff, int picind, int *hdupicind)
+
+{FITS_HDU_LIST *hdulist;
+ int firstpic, lastpic;
+
+ if (ff == NULL)
+ FITS_RETURN ("fits_image_info: ff is NULL", NULL);
+
+ if (ff->openmode != 'r')
+ FITS_RETURN ("fits_image_info: file not open for reading", NULL);
+
+ if ((picind < 1) || (picind > ff->n_pic))
+ FITS_RETURN ("fits_image_info: picind out of range", NULL);
+
+ firstpic = 1;
+ for (hdulist = ff->hdu_list; hdulist != NULL; hdulist = hdulist->next_hdu)
+ {
+ if (hdulist->numpic <= 0) continue;
+ lastpic = firstpic+hdulist->numpic-1;
+ if (picind <= lastpic) /* Found image in current HDU ? */
+ break;
+
+ firstpic = lastpic+1;
+ }
+ *hdupicind = picind - firstpic + 1;
+ return (hdulist);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_seek_image - position to a specific image */
+/* */
+/* Parameters: */
+/* FITS_FILE *ff [I] : FITS file structure */
+/* int picind [I] : Index of picture to seek (1,2,...) */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* The function positions the file pointer to a specified image. */
+/* The function returns on success a pointer to a FITS_HDU_LIST. This pointer*/
+/* must also be used when reading data from the image. */
+/* On failure, NULL is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+FITS_HDU_LIST *fits_seek_image (FITS_FILE *ff, int picind)
+
+{FITS_HDU_LIST *hdulist;
+ int hdupicind;
+ long offset, pic_size;
+
+ hdulist = fits_image_info (ff, picind, &hdupicind);
+ if (hdulist == NULL) return (NULL);
+
+ pic_size = hdulist->bpp * hdulist->naxisn[0] * hdulist->naxisn[1];
+ offset = hdulist->data_offset + (hdupicind-1)*pic_size;
+ if (fseek (ff->fp, offset, SEEK_SET) < 0)
+ FITS_RETURN ("fits_seek_image: Unable to position to image", NULL);
+
+ return (hdulist);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_read_pixel - read pixel values from a file */
+/* */
+/* Parameters: */
+/* FITS_FILE *ff [I] : FITS file structure */
+/* FITS_HDU_LIST *hdulist [I] : pointer to hdulist that describes image */
+/* int npix [I] : number of pixel values to read */
+/* FITS_PIX_TRANSFORM *trans [I]: pixel transformation */
+/* void *buf [O] : buffer where to place transformed pixels */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* The function reads npix pixel values from the file, transforms them */
+/* checking for blank/NaN pixels and stores the transformed values in buf. */
+/* The number of transformed pixels is returned. If the returned value is */
+/* less than npix (or even -1), an error has occured. */
+/* hdulist must be a pointer returned by fits_seek_image(). Before starting */
+/* to read an image, fits_seek_image() must be called. Even for successive */
+/* images. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+int fits_read_pixel (FITS_FILE *ff, FITS_HDU_LIST *hdulist, int npix,
+ FITS_PIX_TRANSFORM *trans, void *buf)
+
+{double offs, scale;
+ double datadiff, pixdiff;
+ unsigned char pixbuffer[4096], *pix, *cdata;
+ unsigned char creplace;
+ int transcount = 0;
+ long tdata, tmin, tmax;
+ int maxelem;
+ FITS_BITPIX8 bp8, bp8blank;
+ FITS_BITPIX16 bp16, bp16blank;
+ FITS_BITPIX32 bp32, bp32blank;
+ FITS_BITPIXM32 bpm32;
+ FITS_BITPIXM64 bpm64;
+
+ /* initialize */
+
+ bpm32 = 0;
+
+ if (ff->openmode != 'r') return (-1); /* Not open for reading */
+ if (trans->dsttyp != 'c') return (-1); /* Currently we only return chars */
+ if (npix <= 0) return (npix);
+
+ datadiff = trans->datamax - trans->datamin;
+ pixdiff = trans->pixmax - trans->pixmin;
+
+ offs = trans->datamin - trans->pixmin*datadiff/pixdiff;
+ scale = datadiff / pixdiff;
+
+ tmin = (long)trans->datamin;
+ tmax = (long)trans->datamax;
+ if (tmin < 0) tmin = 0; else if (tmin > 255) tmin = 255;
+ if (tmax < 0) tmax = 0; else if (tmax > 255) tmax = 255;
+
+ cdata = (unsigned char *)buf;
+ creplace = (unsigned char)trans->replacement;
+
+ switch (hdulist->bitpix)
+ {
+ case 8:
+ while (npix > 0) /* For all pixels to read */
+ {
+ maxelem = sizeof (pixbuffer) / hdulist->bpp;
+ if (maxelem > npix) maxelem = npix;
+ if (fread ((char *)pixbuffer, hdulist->bpp, maxelem, ff->fp) != (unsigned) maxelem)
+ return (-1);
+ npix -= maxelem;
+
+ pix = pixbuffer;
+ if (hdulist->used.blank)
+ {
+ bp8blank = (FITS_BITPIX8)hdulist->blank;
+ while (maxelem--)
+ {
+ bp8 = (FITS_BITPIX8)*(pix++);
+ if (bp8 == bp8blank) /* Is it a blank pixel ? */
+ *(cdata++) = creplace;
+ else /* Do transform */
+ {
+ tdata = (long)(bp8 * scale + offs);
+ if (tdata < tmin) tdata = tmin;
+ else if (tdata > tmax) tdata = tmax;
+ *(cdata++) = (unsigned char)tdata;
+ }
+ transcount++;
+ }
+ }
+ else
+ {
+ while (maxelem--)
+ {
+ bp8 = (FITS_BITPIX8)*(pix++);
+ tdata = (long)(bp8 * scale + offs);
+ if (tdata < tmin) tdata = tmin;
+ else if (tdata > tmax) tdata = tmax;
+ *(cdata++) = (unsigned char)tdata;
+ transcount++;
+ }
+ }
+ }
+ break;
+
+ case 16:
+ while (npix > 0) /* For all pixels to read */
+ {
+ maxelem = sizeof (pixbuffer) / hdulist->bpp;
+ if (maxelem > npix) maxelem = npix;
+ if (fread ((char *)pixbuffer, hdulist->bpp, maxelem, ff->fp) != (unsigned) maxelem)
+ return (-1);
+ npix -= maxelem;
+
+ pix = pixbuffer;
+ if (hdulist->used.blank)
+ {
+ bp16blank = (FITS_BITPIX16)hdulist->blank;
+ while (maxelem--)
+ {
+ FITS_GETBITPIX16 (pix, bp16);
+ if (bp16 == bp16blank)
+ *(cdata++) = creplace;
+ else
+ {
+ tdata = (long)(bp16 * scale + offs);
+ if (tdata < tmin) tdata = tmin;
+ else if (tdata > tmax) tdata = tmax;
+ *(cdata++) = (unsigned char)tdata;
+ }
+ transcount++;
+ pix += 2;
+ }
+ }
+ else
+ {
+ while (maxelem--)
+ {
+ FITS_GETBITPIX16 (pix, bp16);
+ tdata = (long)(bp16 * scale + offs);
+ if (tdata < tmin) tdata = tmin;
+ else if (tdata > tmax) tdata = tmax;
+ *(cdata++) = (unsigned char)tdata;
+ transcount++;
+ pix += 2;
+ }
+ }
+ }
+ break;
+
+ case 32:
+ while (npix > 0) /* For all pixels to read */
+ {
+ maxelem = sizeof (pixbuffer) / hdulist->bpp;
+ if (maxelem > npix) maxelem = npix;
+ if (fread ((char *)pixbuffer, hdulist->bpp, maxelem, ff->fp) != (unsigned) maxelem)
+ return (-1);
+ npix -= maxelem;
+
+ pix = pixbuffer;
+ if (hdulist->used.blank)
+ {
+ bp32blank = (FITS_BITPIX32)hdulist->blank;
+ while (maxelem--)
+ {
+ FITS_GETBITPIX32 (pix, bp32);
+ if (bp32 == bp32blank)
+ *(cdata++) = creplace;
+ else
+ {
+ tdata = (long)(bp32 * scale + offs);
+ if (tdata < tmin) tdata = tmin;
+ else if (tdata > tmax) tdata = tmax;
+ *(cdata++) = (unsigned char)tdata;
+ }
+ transcount++;
+ pix += 4;
+ }
+ }
+ else
+ {
+ while (maxelem--)
+ {
+ FITS_GETBITPIX32 (pix, bp32);
+ tdata = (long)(bp32 * scale + offs);
+ if (tdata < tmin) tdata = tmin;
+ else if (tdata > tmax) tdata = tmax;
+ *(cdata++) = (unsigned char)tdata;
+ transcount++;
+ pix += 4;
+ }
+ }
+ }
+ break;
+
+ case -32:
+ while (npix > 0) /* For all pixels to read */
+ {
+ maxelem = sizeof (pixbuffer) / hdulist->bpp;
+ if (maxelem > npix) maxelem = npix;
+ if (fread ((char *)pixbuffer, hdulist->bpp, maxelem, ff->fp) != (unsigned) maxelem)
+ return (-1);
+ npix -= maxelem;
+
+ pix = pixbuffer;
+ while (maxelem--)
+ {
+ if (fits_nan_32 (pix)) /* An IEEE special value ? */
+ *(cdata++) = creplace;
+ else /* Do transform */
+ {
+ FITS_GETBITPIXM32 (pix, bpm32);
+ tdata = (long)(bpm32 * scale + offs);
+ if (tdata < tmin) tdata = tmin;
+ else if (tdata > tmax) tdata = tmax;
+ *(cdata++) = (unsigned char)tdata;
+ }
+ transcount++;
+ pix += 4;
+ }
+ }
+ break;
+
+ case -64:
+ while (npix > 0) /* For all pixels to read */
+ {
+ maxelem = sizeof (pixbuffer) / hdulist->bpp;
+ if (maxelem > npix) maxelem = npix;
+ if (fread ((char *)pixbuffer, hdulist->bpp, maxelem, ff->fp) != (unsigned) maxelem)
+ return (-1);
+ npix -= maxelem;
+
+ pix = pixbuffer;
+ while (maxelem--)
+ {
+ if (fits_nan_64 (pix))
+ *(cdata++) = creplace;
+ else
+ {
+ FITS_GETBITPIXM64 (pix, bpm64);
+ tdata = (long)(bpm64 * scale + offs);
+ if (tdata < tmin) tdata = tmin;
+ else if (tdata > tmax) tdata = tmax;
+ *(cdata++) = (unsigned char)tdata;
+ }
+ transcount++;
+ pix += 8;
+ }
+ }
+ break;
+ }
+ return (transcount);
+}
+
+
+
+#ifndef FITS_NO_DEMO
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : fits_to_pgmraw - convert FITS-file to raw PGM-file */
+/* */
+/* Parameters: */
+/* char *fitsfile [I] : name of fitsfile */
+/* char *pgmfile [I] : name of pgmfile */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* The function converts a FITS-file to a raw PGM-file. The PGM-file will */
+/* be upside down, because the orientation for storing the image is */
+/* different. On success, 0 is returned. On failure, -1 is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+int fits_to_pgmraw (char *fitsfile, char *pgmfile)
+
+{FITS_FILE *fitsin = NULL;
+ FILE *pgmout = NULL;
+ FITS_HDU_LIST *hdu;
+ FITS_PIX_TRANSFORM trans;
+ int retval = -1, nbytes, maxbytes;
+ char buffer[1024];
+
+ fitsin = fits_open (fitsfile, "r"); /* Open FITS-file for reading */
+ if (fitsin == NULL) goto err_return;
+
+ if (fitsin->n_pic < 1) goto err_return; /* Any picture in it ? */
+
+ hdu = fits_seek_image (fitsin, 1); /* Position to the first image */
+ if (hdu == NULL) goto err_return;
+ if (hdu->naxis < 2) goto err_return; /* Enough dimensions ? */
+
+ pgmout = fopen (pgmfile, "wb");
+ if (pgmout == NULL) goto err_return;
+
+ /* Write PGM header with width/height */
+ fprintf (pgmout, "P5\n%d %d\n255\n", hdu->naxisn[0], hdu->naxisn[1]);
+
+ /* Set up transformation for FITS pixel values to 0...255 */
+ /* It maps trans.pixmin to trans.datamin and trans.pixmax to trans.datamax. */
+ /* Values out of range [datamin, datamax] are clamped */
+ trans.pixmin = hdu->pixmin;
+ trans.pixmax = hdu->pixmax;
+ trans.datamin = 0.0;
+ trans.datamax = 255.0;
+ trans.replacement = 0.0; /* Blank/NaN replacement value */
+ trans.dsttyp = 'c'; /* Output type is character */
+
+ nbytes = hdu->naxisn[0]*hdu->naxisn[1];
+ while (nbytes > 0)
+ {
+ maxbytes = sizeof (buffer);
+ if (maxbytes > nbytes) maxbytes = nbytes;
+
+ /* Read pixels and transform them */
+ if (fits_read_pixel (fitsin, hdu, maxbytes, &trans, buffer) != maxbytes)
+ goto err_return;
+
+ if (fwrite (buffer, 1, maxbytes, pgmout) != maxbytes)
+ goto err_return;
+
+ nbytes -= maxbytes;
+ }
+ retval = 0;
+
+err_return:
+
+ if (fitsin) fits_close (fitsin);
+ if (pgmout) fclose (pgmout);
+
+ return (retval);
+}
+
+
+/*****************************************************************************/
+/* #BEG-PAR */
+/* */
+/* Function : pgmraw to fits - convert raw PGM-file to FITS-file */
+/* */
+/* Parameters: */
+/* char *pgmfile [I] : name of pgmfile */
+/* char *fitsfile [I] : name of fitsfile */
+/* ( mode : I=input, O=output, I/O=input/output ) */
+/* */
+/* The function converts a raw PGM-file to a FITS-file. The FITS-file will */
+/* be upside down, because the orientation for storing the image is */
+/* different. On success, 0 is returned. On failure, -1 is returned. */
+/* */
+/* #END-PAR */
+/*****************************************************************************/
+
+int pgmraw_to_fits (char *pgmfile, char *fitsfile)
+
+{FITS_FILE *fitsout = NULL;
+ FILE *pgmin = NULL;
+ FITS_HDU_LIST *hdu;
+ char buffer[1024];
+ int width, height, numbytes, maxbytes;
+ int retval = -1;
+
+ fitsout = fits_open (fitsfile, "w");
+ if (fitsout == NULL) goto err_return;
+
+ pgmin = fopen (pgmfile, "r");
+ if (pgmin == NULL) goto err_return;
+
+ /* Read signature of PGM file */
+ if (fgets (buffer, sizeof (buffer), pgmin) == NULL) goto err_return;
+ if ((buffer[0] != 'P') || (buffer[1] != '5')) goto err_return;
+
+ /* Skip comments upto width/height */
+ do
+ {
+ if (fgets (buffer, sizeof (buffer), pgmin) == NULL) goto err_return;
+ } while (buffer[0] == '#');
+
+ if (sscanf (buffer, "%d%d", &width, &height) != 2) goto err_return;
+ if ((width < 1) || (height < 1)) goto err_return;
+
+ /* Skip comments upto maxval */
+ do
+ {
+ if (fgets (buffer, sizeof (buffer), pgmin) == NULL) goto err_return;
+ } while (buffer[0] == '#');
+ /* Ignore maxval */
+
+ hdu = fits_add_hdu (fitsout); /* Create a HDU for the FITS file */
+ if (hdu == NULL) goto err_return;
+
+ hdu->used.simple = 1; /* Set proper values */
+ hdu->bitpix = 8;
+ hdu->naxis = 2;
+ hdu->naxisn[0] = width;
+ hdu->naxisn[1] = height;
+ hdu->used.datamin = 1;
+ hdu->datamin = 0.0;
+ hdu->used.datamax = 1;
+ hdu->datamax = 255.0;
+ hdu->used.bzero = 1;
+ hdu->bzero = 0.0;
+ hdu->used.bscale = 1;
+ hdu->bscale = 1.0;
+
+ fits_add_card (hdu, "");
+ fits_add_card (hdu, "HISTORY THIS FITS FILE WAS GENERATED BY FITSRW\
+ USING PGMRAW_TO_FITS");
+
+ /* Write the header. Blocking is done automatically */
+ if (fits_write_header (fitsout, hdu) < 0) goto err_return;
+
+ /* The primary array plus blocking must be written manually */
+ numbytes = width * height;
+
+ while (numbytes > 0)
+ {
+ maxbytes = sizeof (buffer);
+ if (maxbytes > numbytes) maxbytes = numbytes;
+
+ if (fread (buffer, 1, maxbytes, pgmin) != maxbytes) goto err_return;
+ if (fwrite (buffer, 1, maxbytes, fitsout->fp) != maxbytes) goto err_return;
+
+ numbytes -= maxbytes;
+ }
+
+ /* Do blocking */
+ numbytes = (width * height) % FITS_RECORD_SIZE;
+ if (numbytes)
+ {
+ while (numbytes++ < FITS_RECORD_SIZE)
+ if (putc (0, fitsout->fp) == EOF) goto err_return;
+ }
+ retval = 0;
+
+err_return:
+
+ if (fitsout) fits_close (fitsout);
+ if (pgmin) fclose (pgmin);
+
+ return (retval);
+}
+
+#endif
diff --git a/kstars/kstars/indi/fitsrw.h b/kstars/kstars/indi/fitsrw.h
new file mode 100644
index 00000000..9a246930
--- /dev/null
+++ b/kstars/kstars/indi/fitsrw.h
@@ -0,0 +1,283 @@
+/******************************************************************************/
+/* Peter Kirchgessner */
+/* e-mail: pkirchg@aol.com */
+/* WWW : http://members.aol.com/pkirchg */
+/******************************************************************************/
+/* #BEG-HDR */
+/* */
+/* Package : FITS reading/writing library */
+/* Modul-Name : fitsrw.h */
+/* Description : Include file for FITS-r/w-library */
+/* Function(s) : */
+/* Author : P. Kirchgessner */
+/* Date of Gen. : 12-Apr-97 */
+/* Last modified : 17-May-97 */
+/* Version : 0.10 */
+/* Compiler Opt. : */
+/* Changes : */
+/* */
+/* #END-HDR */
+/******************************************************************************/
+
+/** \file fitsrw.h
+ \brief FITS reading/writing library.
+ \author Peter Kirchgessner
+*/
+
+#ifndef FITS_MAX_AXIS
+
+#include <stdio.h>
+
+#define FITS_CARD_SIZE 80
+#define FITS_RECORD_SIZE 2880
+#define FITS_MAX_AXIS 999
+
+#define FITS_NADD_CARDS 128
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Data representations */
+/** \typedef FITS_BITPIX8
+ \brief One byte declared as unsigned char.
+*/
+typedef unsigned char FITS_BITPIX8;
+
+/** \typedef FITS_BITPIX16
+ \brief Two bytes declared as short.
+*/
+typedef short FITS_BITPIX16;
+
+/** \typedef FITS_BITPIX32
+ \brief Four bytes declared as long.
+*/
+typedef long FITS_BITPIX32;
+
+/** \typedef FITS_BITPIXM32
+ \brief IEEE -32 FITS format declared as 4-byte float.
+*/
+typedef float FITS_BITPIXM32;
+
+/** \typedef FITS_BITPIXM64
+ \brief IEEE -64 FITS format declared as 8-byte double.
+*/
+typedef double FITS_BITPIXM64;
+
+typedef int FITS_BOOL;
+typedef long FITS_LONG;
+typedef double FITS_DOUBLE;
+typedef char FITS_STRING[FITS_CARD_SIZE];
+
+typedef enum {
+ typ_bitpix8, typ_bitpix16, typ_bitpix32, typ_bitpixm32, typ_bitpixm64,
+ typ_fbool, typ_flong, typ_fdouble, typ_fstring
+} FITS_DATA_TYPES;
+
+/** \struct FITS_PIX_TRANSFORM
+ \brief A struct that describes how to transform FITS pixel values.
+*
+* The pixel values represent the lower and upper boundaries of the pixel data from the FITS file. The data values represent the range of the final pixel values. For example, to transform FITS pixel values to grey scale, the data min is 0 and data max is 255. The transformation is linear.
+*/
+typedef struct {
+ double pixmin, pixmax; /** The pixel values [pixmin,pixmax] that should be mapped */
+ double datamin, datamax; /** The data values [datamin,datamax] that the pixel values should be mapped to*/
+ double replacement; /** datavalue to use for blank or NaN pixels */
+ char dsttyp; /** Destination typ ('c' = char) */
+} FITS_PIX_TRANSFORM;
+
+typedef union {
+ FITS_BITPIX8 bitpix8;
+ FITS_BITPIX16 bitpix16;
+ FITS_BITPIX32 bitpix32;
+ FITS_BITPIXM32 bitpixm32;
+ FITS_BITPIXM64 bitpixm64;
+
+ FITS_BOOL fbool;
+ FITS_LONG flong;
+ FITS_DOUBLE fdouble;
+ FITS_STRING fstring;
+} FITS_DATA;
+
+/** \struct FITS_RECORD_LIST
+ \brief Record list.
+*/
+typedef struct fits_record_list {
+ unsigned char data[FITS_RECORD_SIZE];
+ struct fits_record_list *next_record;
+} FITS_RECORD_LIST;
+
+/** \struct FITS_HDU_LIST
+ \brief Header and Data Unit List.
+
+* The structure hold header and data unit lists. The \p used struct contains flags specifying if some cards are used.
+*/
+typedef struct fits_hdu_list {
+ long header_offset; /** Offset of header in the file */
+ long data_offset; /** Offset of data in the file */
+ long data_size; /** Size of data in the HDU (including pad)*/
+ long udata_size; /** Size of used data in the HDU (excl. pad) */
+ int bpp; /** Bytes per pixel */
+ int numpic; /** Number of interpretable images in HDU */
+ int naddcards; /** Number of additional cards */
+ char addcards[FITS_NADD_CARDS][FITS_CARD_SIZE];
+ struct {
+ char nan_value; /** NaN's found in data ? */
+ char blank_value; /** Blanks found in data ? */
+
+ char blank;
+ char datamin;
+ char datamax;
+ char simple; /** This indicates a simple HDU */
+ char xtension; /** This indicates an extension */
+ char gcount;
+ char pcount;
+ char bzero;
+ char bscale;
+ char groups;
+ char extend;
+ } used;
+ double pixmin, pixmax; /** Minimum/Maximum pixel values */
+ /* Some decoded data of the HDU: */
+ int naxis; /** Number of axes */
+ int naxisn[FITS_MAX_AXIS]; /** Sizes of axes (NAXIS1 --> naxisn[0]) */
+ int bitpix; /** Data representation (8,16,32,-16,-32) */
+ /* When using the following data, */
+ /* the used-flags must be checked before. */
+ long blank; /** Blank value. Check the \p used struct to verify if this is a valid value*/
+ double datamin, datamax; /** Minimum/Maximum physical data values. Check the \p used struct to verify if this is a valid value*/
+ char xtension[FITS_CARD_SIZE]; /** Type of extension. Check the \p used struct to verify if this is a valid value*/
+ long gcount, pcount; /** Used by XTENSION. Check the \p used struct to verify if this is a valid value*/
+ double bzero, bscale; /** Transformation values. Check the \p used struct to verify if this is a valid value*/
+ int groups; /** Random groups indicator. Check the \p used struct to verify if this is a valid value*/
+ int extend; /** Extend flag. Check the \p used struct to verify if this is a valid value*/
+
+ FITS_RECORD_LIST *header_record_list; /** Header records read in */
+ struct fits_hdu_list *next_hdu;
+} FITS_HDU_LIST;
+
+/** \struct FITS_FILE
+ \brief Structure to hold FITS file information and pointers.
+*/
+typedef struct {
+ FILE *fp; /** File pointer to fits file */
+ char openmode; /** Mode the file was opened (0, 'r', 'w') */
+
+ int n_hdu; /** Number of HDUs in file */
+ int n_pic; /** Total number of interpretable pictures */
+ int nan_used; /** NaN's used in the file ? */
+ int blank_used; /** Blank's used in the file ? */
+
+ FITS_HDU_LIST *hdu_list; /** Header and Data Unit List */
+} FITS_FILE;
+
+
+/* User callable functions of the FITS-library */
+/**
+ * \defgroup fitsFunctions User callable functions of the FITS-library.
+ */
+/*@{*/
+
+/** \brief open a FITS file.
+ \param filename name of file to open
+ \param openmode mode to open the file ("r", "w")
+ \return On success, a FITS_FILE-pointer is returned. On failure, a NULL-pointer is returned. The functions scans through the file loading each header and analyzing them.
+*/
+FITS_FILE *fits_open (const char *filename, const char *openmode);
+
+/** \brief close a FITS file.
+ \param ff FITS file pointer.
+*/
+void fits_close (FITS_FILE *ff);
+
+/** \brief add a HDU to the file.
+ \param ff FITS file pointer.
+ \return Adds a new HDU to the list kept in ff. A pointer to the new HDU is returned. On failure, a NULL-pointer is returned.
+*/
+FITS_HDU_LIST *fits_add_hdu (FITS_FILE *ff);
+
+/** \brief add a card to the HDU.
+ The card must follow the standards of FITS. The card must not use a
+ keyword that is written using *hdulist itself.
+ \param hdulist HDU listr.
+ \param card card to add.
+ \return On success 0 is returned. On failure -1 is returned.
+*/
+int fits_add_card (FITS_HDU_LIST *hdulist, char *card);
+
+/** \brief print the internal representation of a single header.
+ \param hdr pointer to the header
+*/
+void fits_print_header (FITS_HDU_LIST *hdr);
+
+/** \brief write a FITS header to the file.
+ \param ff FITS-file pointer.
+ \param hdulist pointer to header.
+ \return On success, 0 is returned. On failure, -1 is returned.
+*/
+int fits_write_header (FITS_FILE *ff, FITS_HDU_LIST *hdulist);
+
+/** \brief get information about an image.
+ \param ff FITS-file pointer.
+ \param picind Index of picture in file (1,2,...)
+ \param hdupicind Index of picture in HDU (1,2,...)
+ \return The function returns on success a pointer to a FITS_HDU_LIST. hdupicind then gives the index of the image within the HDU. On failure, NULL is returned.
+*/
+FITS_HDU_LIST *fits_image_info (FITS_FILE *ff, int picind, int *hdupicind);
+
+/** \brief position to a specific image.
+ The function positions the file pointer to a specified image.
+ \param ff FITS-file pointer.
+ \param picind Index of picture to seek (1,2,...)
+ \return The function returns on success a pointer to a FITS_HDU_LIST. This pointer must also be used when reading data from the image. On failure, NULL is returned.
+*/
+FITS_HDU_LIST *fits_seek_image (FITS_FILE *ff, int picind);
+
+/** \brief decode a card
+ Decodes a card and returns a pointer to the union, keeping the data.
+ \param card pointer to card image.
+ \param data_type datatype to decode.
+ \return If card is NULL or on failure, a NULL-pointer is returned. If the card does not have the value indicator, an error is generated, but its tried to decode the card. The data is only valid up to the next call of the function.
+*/
+FITS_DATA *fits_decode_card (const char *card, FITS_DATA_TYPES data_type);
+
+/** \brief search a card in the record list.
+ A card is searched in the reord list. Only the first eight characters of keyword are significant. If keyword is less than 8 characters, its filled with blanks.
+ \param rl record list to search.
+ \param keyword keyword identifying the card.
+ \return If the card is found, a pointer to the card is returned. The pointer does not point to a null-terminated string. Only the next 80 bytes are allowed to be read. On failure a NULL-pointer is returned.
+*/
+char *fits_search_card (FITS_RECORD_LIST *rl, const char *keyword);
+
+/** \brief read pixel values from a file
+ The function reads npix pixel values from the file, transforms them checking for blank/NaN pixels and stores the transformed values in buf. hdulist must be a pointer returned by fits_seek_image(). Before starting to read an image, fits_seek_image() must be called. Even for successive images.
+ \param ff FITS file structure.
+ \param hdulist pointer to hdulist that describes image.
+ \param npix number of pixel values to read.
+ \param trans pixel transformation.
+ \param buf buffer where to place transformed pixels.
+ \return The number of transformed pixels is returned. If the returned value is less than npix (or even -1), an error has occured.
+*/
+int fits_read_pixel (FITS_FILE *ff, FITS_HDU_LIST *hdulist,
+ int npix, FITS_PIX_TRANSFORM *trans, void *buf);
+
+/** \brief get an error message.
+ \return If an error message has been set, a pointer to the message is returned. Otherwise a NULL pointer is returned. An inquired error message is removed from the error FIFO.
+*/
+char *fits_get_error (void);
+
+/*@}*/
+
+int fits_nan_32 (unsigned char *v);
+int fits_nan_64 (unsigned char *v);
+
+/* Demo functions */
+#define FITS_NO_DEMO
+int fits_to_pgmraw (char *fitsfile, char *pgmfile);
+int pgmraw_to_fits (char *pgmfile, char *fitsfile);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/kstars/kstars/indi/fli/Makefile.am b/kstars/kstars/indi/fli/Makefile.am
new file mode 100644
index 00000000..859b459e
--- /dev/null
+++ b/kstars/kstars/indi/fli/Makefile.am
@@ -0,0 +1,24 @@
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+if LINUX
+libfli_linux = libfli_linux.la
+endif
+
+if BSD
+libfli_bsd = libfli_bsd.la
+endif
+
+if NULL
+libfli_null = libfli_null.la
+endif
+
+noinst_LTLIBRARIES = libfli.la $(libfli_linux) $(libfli_bsd) $(libfli_null)
+
+libfli_linux_la_SOURCES = libfli-parport.c libfli-usb-sys-linux.c
+libfli_bsd_la_SOURCES = libfli-usb-sys-bsd.c
+libfli_null_la_SOURCES = libfli-usb-sys-null.c
+
+libfli_la_SOURCES = libfli.c libfli-camera.c libfli-camera-parport.c libfli-camera-usb.c libfli-filter-focuser.c libfli-mem.c libfli-serial.c libfli-sys.c libfli-usb.c libfli-debug.c
+AM_LDFLAGS = $(all_libraries)
+libfli_la_LIBADD = $(libfli_linux) $(libfli_bsd) $(libfli_null)
diff --git a/kstars/kstars/indi/fli/fli_ioctl.h b/kstars/kstars/indi/fli/fli_ioctl.h
new file mode 100644
index 00000000..63dae274
--- /dev/null
+++ b/kstars/kstars/indi/fli/fli_ioctl.h
@@ -0,0 +1,119 @@
+/*
+
+ Copyright (c) 2000 Finger Lakes Instrumentation (FLI), LLC.
+ 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 (FLI)
+ web: http://www.fli-cam.com
+ email: fli@rpa.net
+
+*/
+
+#ifndef _FLI_IOCTL_H
+#define _FLI_IOCTL_H
+
+#include <asm/ioctl.h>
+
+/* 8-bit special value to identify ioctl 'type' */
+#define FLI_IOCTL_TYPE 'F'
+
+/* Macros declaring ioctl commands and the variables they operate on */
+#define FLI_IOCTL_MISC_CMDS \
+ FLI_IOCTL_CMD(FLI_RESET_PORT_VALUES, **NONE**) \
+ FLI_IOCTL_CMD(FLI_LOCK_PORT, **NONE**) \
+ FLI_IOCTL_CMD(FLI_UNLOCK_PORT, **NONE**)
+
+#define FLI_IOCTL_SPECIAL_SET_CMDS \
+ FLI_IOCTL_CMD(FLI_SET_DMABUFFSIZE, dmabuffsize)
+
+#define FLI_IOCTL_SET_CMDS \
+ FLI_IOCTL_CMD(FLI_SET_DMATHRESH, dmathresh) \
+ FLI_IOCTL_CMD(FLI_SET_DTO, dto) \
+ FLI_IOCTL_CMD(FLI_SET_RTO, rto) \
+ FLI_IOCTL_CMD(FLI_SET_WTO, wto) \
+ FLI_IOCTL_CMD(FLI_SET_LTL, ltl) \
+ FLI_IOCTL_CMD(FLI_SET_DIR, dir) \
+ FLI_IOCTL_CMD(FLI_SET_NUMREAD, numread) \
+ FLI_IOCTL_CMD(FLI_SET_NUMWRITE, numwrite) \
+ FLI_IOCTL_CMD(FLI_SET_NUMDTO, numdto) \
+ FLI_IOCTL_CMD(FLI_SET_NUMRTO, numrto) \
+ FLI_IOCTL_CMD(FLI_SET_NUMWTO, numwto)
+
+#define FLI_IOCTL_GET_CMDS \
+ FLI_IOCTL_CMD(FLI_GET_DMABUFFSIZE, dmabuffsize) \
+ FLI_IOCTL_CMD(FLI_GET_DMATHRESH, dmathresh) \
+ FLI_IOCTL_CMD(FLI_GET_DTO, dto) \
+ FLI_IOCTL_CMD(FLI_GET_RTO, rto) \
+ FLI_IOCTL_CMD(FLI_GET_WTO, wto) \
+ FLI_IOCTL_CMD(FLI_GET_DIR, dir) \
+ FLI_IOCTL_CMD(FLI_GET_LTL, ltl) \
+ FLI_IOCTL_CMD(FLI_GET_NUMREAD, numread) \
+ FLI_IOCTL_CMD(FLI_GET_NUMWRITE, numwrite) \
+ FLI_IOCTL_CMD(FLI_GET_NUMDTO, numdto) \
+ FLI_IOCTL_CMD(FLI_GET_NUMRTO, numrto) \
+ FLI_IOCTL_CMD(FLI_GET_NUMWTO, numwto)
+
+/* Enumerate ioctl numbers */
+#undef FLI_SET_CMD
+#define FLI_IOCTL_CMD(cmd, var) cmd##_NUM,
+
+enum {
+ FLI_IOCTL_MISC_CMDS
+ FLI_IOCTL_SPECIAL_SET_CMDS
+ FLI_IOCTL_SET_CMDS
+ FLI_IOCTL_GET_CMDS
+};
+
+/* Enumerate the actual ioctl commands */
+#undef FLI_IOCTL_CMD
+#define FLI_IOCTL_CMD(cmd, var) \
+ enum {cmd = _IO(FLI_IOCTL_TYPE, cmd##_NUM)};
+
+FLI_IOCTL_MISC_CMDS;
+
+#undef FLI_IOCTL_CMD
+#define FLI_IOCTL_CMD(cmd, var) \
+ enum {cmd = _IOW(FLI_IOCTL_TYPE, cmd##_NUM, int)};
+
+FLI_IOCTL_SPECIAL_SET_CMDS;
+FLI_IOCTL_SET_CMDS;
+
+#undef FLI_IOCTL_CMD
+#define FLI_IOCTL_CMD(cmd, var ) \
+ enum {cmd = _IOR(FLI_IOCTL_TYPE, cmd##_NUM, int)};
+
+FLI_IOCTL_GET_CMDS;
+
+#endif /* _FLI_IOCTL_H */
diff --git a/kstars/kstars/indi/fli/libfli-camera-parport.c b/kstars/kstars/indi/fli/libfli-camera-parport.c
new file mode 100644
index 00000000..bd5343ce
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-camera-parport.c
@@ -0,0 +1,753 @@
+/*
+
+ 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 "libfli-libfli.h"
+#include "libfli-mem.h"
+#include "libfli-debug.h"
+#include "libfli-camera.h"
+#include "libfli-camera-parport.h"
+
+long fli_camera_parport_open(flidev_t dev)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf;
+ int id;
+
+ cam = DEVICE->device_data;
+
+ /* Set timeout values */
+ cam->readto = 1000;
+ cam->writeto = 1000;
+ cam->dirto = 1000;
+
+ rlen = 2;
+ wlen = 2;
+ buf = htons(C_ADDRESS(1, EPARAM_ECHO));
+ IO(dev, &buf, &wlen, &rlen);
+ if (buf != htons(C_ADDRESS(1, EPARAM_ECHO)))
+ {
+ debug(FLIDEBUG_FAIL, "Echo back from camera failed.");
+ return -EIO;
+ }
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_ADDRESS(1, EPARAM_DEVICE));
+ IO(dev, &buf, &wlen, &rlen);
+ DEVICE->devinfo.hwrev = ntohs(buf) & 0x00ff;
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_ADDRESS(1, EPARAM_CCDID));
+ IO(dev, &buf, &wlen, &rlen);
+ DEVICE->devinfo.devid = ntohs(buf) & 0x00ff;
+
+ 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.array_area.ul.x = knowndev[id].array_area.ul.x;
+ cam->ccd.array_area.ul.y = knowndev[id].array_area.ul.y;
+ cam->ccd.array_area.lr.x = knowndev[id].array_area.lr.x;
+ cam->ccd.array_area.lr.y = knowndev[id].array_area.lr.y;
+ cam->ccd.visible_area.ul.x = knowndev[id].visible_area.ul.x;
+ cam->ccd.visible_area.ul.y = knowndev[id].visible_area.ul.y;
+ cam->ccd.visible_area.lr.x = knowndev[id].visible_area.lr.x;
+ cam->ccd.visible_area.lr.y = knowndev[id].visible_area.lr.y;
+ cam->ccd.pixelwidth = knowndev[id].pixelwidth;
+ cam->ccd.pixelheight = knowndev[id].pixelheight;
+
+ if ((DEVICE->devinfo.model =
+ (char *)xmalloc(strlen(knowndev[id].model) + 1)) == NULL)
+ return -ENOMEM;
+ strcpy(DEVICE->devinfo.model, knowndev[id].model);
+
+ 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);
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_ADDRESS(1, EPARAM_SNHIGH));
+ IO(dev, &buf, &wlen, &rlen);
+ DEVICE->devinfo.serno = (ntohs(buf) & 0x00ff) << 8;
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_ADDRESS(1, EPARAM_SNLOW));
+ IO(dev, &buf, &wlen, &rlen);
+ DEVICE->devinfo.serno |= (ntohs(buf) & 0x00ff);
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_ADDRESS(1, EPARAM_FIRM));
+ IO(dev, &buf, &wlen, &rlen);
+ DEVICE->devinfo.fwrev = (ntohs(buf) & 0x00ff);
+
+ /* Initialize all varaibles to something */
+ switch(DEVICE->devinfo.hwrev)
+ {
+ case 0x01:
+ cam->tempslope = (100.0 / 201.1);
+ cam->tempintercept = (-61.613);
+ break;
+
+ case 0x02:
+ cam->tempslope = (70.0 / 215.75);
+ cam->tempintercept = (-52.5681);
+ break;
+
+ default:
+ debug(FLIDEBUG_WARN, "Could not set temperature parameters.");
+ break;
+ }
+
+ 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->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_parport_get_array_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ *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_parport_get_visible_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ *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_parport_set_exposure_time(flidev_t dev, long exptime)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if (exptime < 0)
+ return -EINVAL;
+
+ cam->exposure = exptime;
+
+ if (exptime <= 15000) /* Less than thirty seconds..., 8.192e-3 sec */
+ {
+ cam->expdur = 1;
+ cam->expmul = (long) (((double) exptime) / 8.192);
+ }
+ else if (exptime <= 2000000) /* Less than one hour */
+ {
+ cam->expdur = (long) (1.0 / 8.192e-3);
+ cam->expmul = (long) (exptime / 1000);
+ }
+ else
+ {
+ cam->expdur = (long) (10.0 / 8.192e-3);
+ cam->expmul = (long) (exptime / 10000);
+ }
+
+ return 0;
+}
+
+long fli_camera_parport_set_image_area(flidev_t dev, long ul_x, long ul_y,
+ long lr_x, long lr_y)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if ((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 -EINVAL;
+
+ 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;
+
+ return 0;
+}
+
+long fli_camera_parport_set_hbin(flidev_t dev, long hbin)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if ((hbin < 1) || (hbin > 16))
+ return -EINVAL;
+
+ cam->hbin = hbin;
+ return 0;
+}
+
+long fli_camera_parport_set_vbin(flidev_t dev, long vbin)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if ((vbin < 1) || (vbin > 16))
+ return -EINVAL;
+
+ cam->vbin = vbin;
+ return 0;
+}
+
+long fli_camera_parport_get_exposure_status(flidev_t dev, long *timeleft)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf;
+
+ cam = DEVICE->device_data;
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_SHUTTER(1,0));
+ IO(dev, &buf, &wlen, &rlen);
+ if ((ntohs(buf) & 0xf000) != C_SHUTTER(0,0))
+ {
+ debug(FLIDEBUG_FAIL, "(exposurestatus) echo back from camera failed.");
+ return -EIO;
+ }
+
+ *timeleft = (long)((double)(ntohs(buf) & 0x07ff) *
+ ((double)cam->expdur * 8.192));
+
+ return 0;
+}
+
+long fli_camera_parport_set_temperature(flidev_t dev, double temperature)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf;
+
+ cam = DEVICE->device_data;
+
+ rlen = 2; wlen = 2;
+ buf = (unsigned short)((temperature - cam->tempintercept) /
+ cam->tempslope);
+ buf = htons((unsigned short) C_TEMP(buf));
+ IO(dev, &buf, &wlen, &rlen);
+ if ((ntohs(buf) & 0xf000) != C_TEMP(0))
+ {
+ debug(FLIDEBUG_FAIL, "(settemperature) echo back from camera failed.");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+long fli_camera_parport_get_temperature(flidev_t dev, double *temperature)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf;
+
+ cam = DEVICE->device_data;
+
+ rlen = 2; wlen = 2;
+ buf = htons(C_TEMP(0x0800));
+ IO(dev, &buf, &wlen, &rlen);
+ if ((ntohs(buf) & 0xf000) != C_TEMP(0))
+ {
+ debug(FLIDEBUG_FAIL, "(settemperature) echo back from camera failed.");
+ return -EIO;
+ }
+ *temperature = cam->tempslope * (double)(ntohs(buf) & 0x00ff) +
+ cam->tempintercept;
+
+ return 0;
+}
+
+long fli_camera_parport_grab_row(flidev_t dev, void *buff, size_t width)
+{
+ flicamdata_t *cam;
+ long r;
+ double dTm;
+ long rlen, wlen;
+ unsigned short buf;
+
+ cam = DEVICE->device_data;
+
+ if (cam->flushcountbeforefirstrow > 0)
+ {
+ if ((r = fli_camera_parport_flush_rows(dev,
+ cam->flushcountbeforefirstrow, 1)))
+ return r;
+
+ cam->flushcountbeforefirstrow = 0;
+ }
+
+ dTm = (25.0e-6) * cam->ccd.array_area.lr.x + 1e-3;
+ dTm = dTm / 1e-6;
+ cam->readto = (long)dTm;
+ cam->writeto = (long)dTm;
+
+ rlen = 0; wlen = 2;
+ buf = htons((unsigned short) C_SEND(cam->grabrowwidth));
+ IO(dev, &buf, &wlen, &rlen);
+
+ if (cam->bitdepth == FLI_MODE_8BIT)
+ {
+ unsigned char *cbuf;
+ int x;
+
+ if ((cbuf = xmalloc(cam->grabrowwidth)) == NULL)
+ {
+ debug(FLIDEBUG_FAIL, "Failed memory allocation during row grab.");
+ return -ENOMEM;
+ }
+
+ rlen = cam->grabrowwidth; wlen = 0;
+ r = DEVICE->fli_io(dev, cbuf, &wlen, &rlen);
+ if (r != 0)
+ {
+ debug(FLIDEBUG_WARN, "Couldn't grab entire row, got %d of %d bytes.",
+ rlen, cam->grabrowwidth);
+ }
+ for (x = 0; x < (int)width; x++)
+ {
+ ((char *)buff)[x] = (((cbuf[x]) + 128) & 0x00ff);
+ }
+ xfree(cbuf);
+ }
+ else
+ {
+ unsigned short *sbuf;
+ int x;
+
+ if ((sbuf = xmalloc(cam->grabrowwidth * sizeof(unsigned short))) == NULL)
+ {
+ debug(FLIDEBUG_FAIL, "Failed memory allocation during row grab.");
+ return -ENOMEM;
+ }
+
+ rlen = cam->grabrowwidth * sizeof(unsigned short); wlen = 0;
+ r = DEVICE->fli_io(dev, sbuf, &wlen, &rlen);
+ if (r != 0)
+ {
+ debug(FLIDEBUG_WARN, "Couldn't grab entire row, got %d of %d bytes.",
+ rlen, cam->grabrowwidth);
+ }
+ for (x = 0; x < (int)width; x++)
+ {
+ if (DEVICE->devinfo.hwrev == 0x01) /* IMG camera */
+ {
+ ((unsigned short *)buff)[x] = ntohs(sbuf[x]) + 32768;
+ }
+ else
+ {
+ ((unsigned short *)buff)[x] = ntohs(sbuf[x]);
+ }
+ }
+ xfree(sbuf);
+ }
+
+ rlen = 2; wlen = 0;
+ IO(dev, &buf, &wlen, &rlen);
+ if (ntohs(buf) != C_SEND(width))
+ {
+ debug(FLIDEBUG_WARN, "Width: %d, requested %d.",
+ width, cam->grabrowwidth * sizeof(unsigned short));
+ debug(FLIDEBUG_WARN, "Got 0x%04x instead of 0x%04x.", ntohs(buf), C_SEND(width));
+ debug(FLIDEBUG_WARN, "Didn't get command echo at end of row.");
+ }
+
+ if (cam->grabrowcount > 0)
+ {
+ cam->grabrowcount--;
+ if (cam->grabrowcount == 0)
+ {
+ if ((r = fli_camera_parport_flush_rows(dev,
+ cam->flushcountafterlastrow, 1)))
+ return r;
+
+ cam->flushcountafterlastrow = 0;
+ cam->grabrowbatchsize = 1;
+ }
+ }
+
+ cam->readto = 1000;
+ cam->writeto = 1000;
+
+ return 0;
+}
+
+long fli_camera_parport_expose_frame(flidev_t dev)
+{
+ flicamdata_t *cam;
+ long rlen, wlen;
+ unsigned short buf;
+
+ cam = DEVICE->device_data;
+
+ debug(FLIDEBUG_INFO, "Setting X Row Offset.");
+ rlen = 2; wlen = 2;
+ buf = htons((unsigned short) D_XROWOFF(cam->image_area.ul.x));
+ IO(dev, &buf, &wlen, &rlen);
+
+ debug(FLIDEBUG_INFO, "Setting X Row Width to %d.", cam->ccd.array_area.lr.x - cam->ccd.array_area.ul.x);
+ buf = htons((unsigned short) D_XROWWID(cam->ccd.array_area.lr.x - cam->ccd.array_area.ul.x));
+ IO(dev, &buf, &wlen, &rlen);
+
+ debug(FLIDEBUG_INFO, "Setting X Flush Bin.");
+ buf = htons((unsigned short) D_XFLBIN(cam->hflushbin));
+ IO(dev, &buf, &wlen, &rlen);
+
+ debug(FLIDEBUG_INFO, "Setting Y Flush Bin.");
+ buf = htons((unsigned short) D_YFLBIN(cam->vflushbin));
+ IO(dev, &buf, &wlen, &rlen);
+
+ debug(FLIDEBUG_INFO, "Setting X Bin.");
+ buf = htons((unsigned short) D_XBIN(cam->hbin));
+ IO(dev, &buf, &wlen, &rlen);
+
+ debug(FLIDEBUG_INFO, "Setting Y Bin.");
+ buf = htons((unsigned short) D_YBIN(cam->vbin));
+ IO(dev, &buf, &wlen, &rlen);
+
+ debug(FLIDEBUG_INFO, "Setting Exposure Duration.");
+ buf = htons((unsigned short) D_EXPDUR(cam->expdur));
+ IO(dev, &buf, &wlen, &rlen);
+
+ if (cam->bitdepth == FLI_MODE_8BIT)
+ {
+ debug(FLIDEBUG_INFO, "Eight Bit.");
+ buf = htons((unsigned short)((cam->exttrigger > 0) ?
+ C_RESTCFG(0,0,1,7) : C_RESTCFG(0,0,0,7)));
+ }
+ else
+ {
+ debug(FLIDEBUG_INFO, "Sixteen Bit.");
+ buf = htons((unsigned short)((cam->exttrigger > 0) ?
+ C_RESTCFG(0,0,1,15) :
+ C_RESTCFG(0,0,0,15)));
+ }
+ IO(dev, &buf, &wlen, &rlen);
+
+ if (cam->flushes > 0)
+ {
+ int r;
+
+ debug(FLIDEBUG_INFO, "Flushing array.");
+ if ((r = fli_camera_parport_flush_rows(dev,
+ cam->ccd.array_area.lr.y - cam->ccd.array_area.ul.y,
+ cam->flushes)))
+ return r;
+ }
+
+ debug(FLIDEBUG_INFO, "Exposing.");
+ buf = htons((unsigned short) C_SHUTTER((cam->frametype == FLI_FRAME_TYPE_DARK)?0:1,
+ cam->expmul));
+ IO(dev, &buf, &wlen, &rlen);
+
+ cam->grabrowwidth = cam->image_area.lr.x - cam->image_area.ul.x;
+ 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->flushcountafterlastrow < 0)
+ cam->flushcountafterlastrow = 0;
+
+ cam->grabrowcount = cam->image_area.lr.y - cam->image_area.ul.y;
+
+ return 0;
+}
+
+long fli_camera_parport_flush_rows(flidev_t dev, long rows, long repeat)
+{
+ flicamdata_t *cam;
+ double dTm;
+ long rlen, wlen;
+ unsigned short buf;
+
+ if (rows < 0)
+ return -EINVAL;
+
+ if (rows == 0)
+ return 0;
+
+ cam = DEVICE->device_data;
+
+ dTm = ((25e-6) / (cam->hflushbin / 2)) * cam->ccd.array_area.lr.x + 1e-3;
+ dTm = dTm * rows;
+ dTm = dTm / 1e-6;
+ cam->readto = (long)dTm;
+ cam->writeto = (long)dTm;
+
+ while (repeat>0)
+ {
+ long retval;
+
+ rlen = 2; wlen = 2;
+ buf = htons((unsigned short) C_FLUSH(rows));
+ retval = DEVICE->fli_io(dev, &buf, &wlen, &rlen);
+ if (retval != 0)
+ {
+ cam->readto = 1000;
+ cam->writeto = 1000;
+ return retval;
+ }
+ repeat--;
+ }
+
+ return 0;
+}
+
+long fli_camera_parport_set_bit_depth(flidev_t dev, flibitdepth_t bitdepth)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if (DEVICE->devinfo.type != 0x01) /* IMG cameras only support this */
+ return -EINVAL;
+
+ if ((bitdepth != FLI_MODE_8BIT) && (bitdepth != FLI_MODE_16BIT))
+ {
+ debug(FLIDEBUG_FAIL, "Invalid bit depth setting.");
+ return -EINVAL;
+ }
+
+ cam->bitdepth = bitdepth;
+
+ return 0;
+}
+
+static void correctioportdatawrite(flidev_t dev, unsigned short *Data)
+{
+ unsigned short data;
+
+ data = 0;
+
+ switch(DEVICE->devinfo.hwrev)
+ {
+ case 0x01:
+ data |= (*Data & FLICCD_IO_P0)?0x01:0;
+ data |= (*Data & FLICCD_IO_P1)?0x02:0;
+ data |= (*Data & FLICCD_IO_P2)?0x04:0;
+ data |= (*Data & FLICCD_IO_P3)?0x80:0;
+ break;
+
+ case 0x02:
+ data |= (*Data & FLICCD_IO_P0)?0x08:0;
+ data |= (*Data & FLICCD_IO_P1)?0x10:0;
+ data |= (*Data & FLICCD_IO_P2)?0x20:0;
+ data |= (*Data & FLICCD_IO_P3)?0x40:0;
+ break;
+
+ default:
+ break;
+ }
+
+ *Data = data;
+
+ return;
+}
+
+static void correctioportdataread(flidev_t dev, unsigned short *Data)
+{
+ unsigned short data;
+
+ data = 0;
+
+ switch (DEVICE->devinfo.hwrev)
+ {
+ case 0x01:
+ data |= (*Data & 0x01)?FLICCD_IO_P0:0;
+ data |= (*Data & 0x02)?FLICCD_IO_P1:0;
+ data |= (*Data & 0x04)?FLICCD_IO_P2:0;
+ data |= (*Data & 0x80)?FLICCD_IO_P3:0;
+ break;
+
+ case 0x02:
+ data |= (*Data & 0x08)?FLICCD_IO_P0:0;
+ data |= (*Data & 0x10)?FLICCD_IO_P1:0;
+ data |= (*Data & 0x20)?FLICCD_IO_P2:0;
+ data |= (*Data & 0x40)?FLICCD_IO_P3:0;
+ break;
+
+ default:
+ break;
+ }
+
+ *Data = data;
+
+ return;
+}
+
+long fli_camera_parport_read_ioport(flidev_t dev, long *ioportset)
+{
+ long rlen, wlen;
+ unsigned short buf;
+
+ rlen = 2; wlen = 2;
+ buf = htons(0x7900);
+ IO(dev, &buf, &wlen, &rlen);
+
+ *ioportset = ntohs(buf) & 0x00ff;
+ correctioportdataread(dev, (unsigned short *) ioportset);
+
+ return 0;
+}
+
+long fli_camera_parport_write_ioport(flidev_t dev, long ioportset)
+{
+ long rlen, wlen;
+ unsigned short buf = (unsigned short) ioportset;
+
+ correctioportdatawrite(dev, &buf);
+ buf = htons((unsigned short) (0x7100 | (buf & 0x00ff)));
+
+ rlen = 2; wlen = 2;
+ IO(dev, &buf, &wlen, &rlen);
+
+ return 0;
+}
+
+long fli_camera_parport_configure_ioport(flidev_t dev, long ioportset)
+{
+ long rlen, wlen;
+ unsigned short buf = (unsigned short) ioportset;
+
+ correctioportdatawrite(dev, &buf);
+ buf = htons((unsigned short) (0x7000 | (buf & 0x00ff)));
+
+ rlen = 2; wlen = 2;
+ IO(dev, &buf, &wlen, &rlen);
+
+ return 0;
+}
+
+long fli_camera_parport_control_shutter(flidev_t dev, long shutter)
+{
+ long rlen, wlen;
+ unsigned short buf;
+
+ rlen = 2; wlen = 2;
+ buf = htons(D_EXPDUR(0));
+ IO(dev, &buf, &wlen, &rlen);
+
+ switch (shutter)
+ {
+ case FLI_SHUTTER_CLOSE:
+ debug(FLIDEBUG_INFO, "Closing shutter.");
+ buf = htons(C_SHUTTER(0, 0));
+ IO(dev, &buf, &wlen, &rlen);
+ break;
+
+ case FLI_SHUTTER_OPEN:
+ buf = htons(C_SHUTTER(1, 1));
+ IO(dev, &buf, &wlen, &rlen);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/kstars/kstars/indi/fli/libfli-camera-parport.h b/kstars/kstars/indi/fli/libfli-camera-parport.h
new file mode 100644
index 00000000..12745098
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-camera-parport.h
@@ -0,0 +1,102 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_CAMERA_PARPORT_H_
+#define _LIBFLI_CAMERA_PARPORT_H_
+
+/* Define command and data word formats */
+#define C_ADDRESS(addr,ext) (0x8000|(((addr)<<8)&0x0f00)|((ext)&0x00ff))
+#define C_RESTCFG(gain,chnl,exttrig,res) (0x9000|(((gain)<<8)&0x0f00)|(((chnl)<<5)&0x00e0)|(((exttrig)<<4)&0x0010)|(((res)&0x000f)))
+#define C_SHUTTER(open,dmult) (0xa000|((dmult)&0x07ff)|(((open)<<11)&0x0800))
+#define C_SEND(x) (0xb000|((x)&0x0fff))
+#define C_FLUSH(x) (0xc000|((x)&0x0fff))
+#define C_VSKIP(x) (0xd000|((x)&0x0fff))
+#define C_HSKIP(x) (0xe000|((x)&0x0fff))
+#define C_TEMP(x) (0xf000|((x)&0x0fff))
+#define D_XROWOFF(x) (0x0000|((x)&0x0fff))
+#define D_XROWWID(x) (0x1000|((x)&0x0fff))
+#define D_XFLBIN(x) (0x2000|((x)&0x0fff))
+#define D_YFLBIN(x) (0x3000|((x)&0x0fff))
+#define D_XBIN(x) (0x4000|((x)&0x0fff))
+#define D_YBIN(x) (0x5000|((x)&0x0fff))
+#define D_EXPDUR(x) (0x6000|((x)&0x0fff))
+#define D_RESERVE(x) (0x7000|((x)&0x0fff))
+
+/* Define extended parameter fields for querying camera */
+#define EPARAM_ECHO (0x00)
+#define EPARAM_CCDID (0x01)
+#define EPARAM_FIRM (0x02)
+#define EPARAM_SNHIGH (0x03)
+#define EPARAM_SNLOW (0x04)
+#define EPARAM_SIGGAIN (0x05)
+#define EPARAM_DEVICE (0x06)
+
+/* I/O Bit definitions */
+#define FLICCD_IO_P0 (0x01)
+#define FLICCD_IO_P1 (0x02)
+#define FLICCD_IO_P2 (0x04)
+#define FLICCD_IO_P3 (0x08)
+
+long fli_camera_parport_open(flidev_t dev);
+long fli_camera_parport_get_array_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y);
+long fli_camera_parport_get_visible_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y);
+long fli_camera_parport_set_exposure_time(flidev_t dev, long exptime);
+long fli_camera_parport_set_image_area(flidev_t dev, long ul_x, long ul_y,
+ long lr_x, long lr_y);
+long fli_camera_parport_set_hbin(flidev_t dev, long hbin);
+long fli_camera_parport_set_vbin(flidev_t dev, long vbin);
+long fli_camera_parport_get_exposure_status(flidev_t dev, long *timeleft);
+long fli_camera_parport_set_temperature(flidev_t dev, double temperature);
+long fli_camera_parport_get_temperature(flidev_t dev, double *temperature);
+long fli_camera_parport_grab_row(flidev_t dev, void *buf, size_t width);
+long fli_camera_parport_expose_frame(flidev_t dev);
+long fli_camera_parport_flush_rows(flidev_t dev, long rows, long repeat);
+long fli_camera_parport_set_bit_depth(flidev_t dev, flibitdepth_t bitdepth);
+long fli_camera_parport_read_ioport(flidev_t dev, long *ioportset);
+long fli_camera_parport_write_ioport(flidev_t dev, long ioportset);
+long fli_camera_parport_configure_ioport(flidev_t dev, long ioportset);
+long fli_camera_parport_control_shutter(flidev_t dev, long shutter);
+
+#endif /* _LIBFLI_CAMERA_PARPORT_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-camera-usb.c b/kstars/kstars/indi/fli/libfli-camera-usb.c
new file mode 100644
index 00000000..6bc88f1f
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-camera-usb.c
@@ -0,0 +1,776 @@
+/*
+
+ 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;
+}
diff --git a/kstars/kstars/indi/fli/libfli-camera-usb.h b/kstars/kstars/indi/fli/libfli-camera-usb.h
new file mode 100644
index 00000000..f2c79037
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-camera-usb.h
@@ -0,0 +1,98 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_CAMERA_USB_H_
+#define _LIBFLI_CAMERA_USB_H_
+
+#define FLI_USBCAM_DEVICENAME 0x01
+#define FLI_USBCAM_DEVICEMFG 0x02
+#define FLI_USBCAM_VERSION 0x03
+#define FLI_USBCAM_DEVICEID 0x04
+#define FLI_USBCAM_SERIALNUM 0x05
+#define FLI_USBCAM_HARDWAREREV 0x06
+#define FLI_USBCAM_DEVINIT 0x07
+#define FLI_USBCAM_READPARAMBLOCK 0x08
+
+#define FLI_USBCAM_ARRAYSIZE 0x100
+#define FLI_USBCAM_IMAGEOFFSET 0x102
+#define FLI_USBCAM_IMAGESIZE 0x103
+#define FLI_USBCAM_TEMPERATURE 0x104
+#define FLI_USBCAM_SETFRAMEOFFSET 0x105
+#define FLI_USBCAM_SETBINFACTORS 0x106
+#define FLI_USBCAM_SETFLUSHBINFACTORS 0x107
+#define FLI_USBCAM_SETEXPOSURE 0x108
+#define FLI_USBCAM_STARTEXPOSURE 0x109
+#define FLI_USBCAM_ABORTEXPOSURE 0x10a
+#define FLI_USBCAM_EXPOSURESTATUS 0x10b
+#define FLI_USBCAM_FLUSHROWS 0x10c
+#define FLI_USBCAM_SENDROW 0x10d
+#define FLI_USBCAM_SHUTTER 0x10f
+#define FLI_USBCAM_WRITEIO 0x110
+#define FLI_USBCAM_READIO 0x111
+#define FLI_USBCAM_WRITEDIR 0x112
+#define FLI_USBCAM_BGFLUSH 0x114
+
+long fli_camera_usb_open(flidev_t dev);
+long fli_camera_usb_get_array_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y);
+long fli_camera_usb_get_visible_area(flidev_t dev, long *ul_x, long *ul_y,
+ long *lr_x, long *lr_y);
+long fli_camera_usb_set_exposure_time(flidev_t dev, long exptime);
+long fli_camera_usb_set_image_area(flidev_t dev, long ul_x, long ul_y,
+ long lr_x, long lr_y);
+long fli_camera_usb_set_hbin(flidev_t dev, long hbin);
+long fli_camera_usb_set_vbin(flidev_t dev, long vbin);
+long fli_camera_usb_get_exposure_status(flidev_t dev, long *timeleft);
+long fli_camera_usb_set_temperature(flidev_t dev, double temperature);
+long fli_camera_usb_get_temperature(flidev_t dev, double *temperature);
+long fli_camera_usb_grab_row(flidev_t dev, void *buff, size_t width);
+long fli_camera_usb_expose_frame(flidev_t dev);
+long fli_camera_usb_flush_rows(flidev_t dev, long rows, long repeat);
+long fli_camera_usb_set_bit_depth(flidev_t dev, flibitdepth_t bitdepth);
+long fli_camera_usb_read_ioport(flidev_t dev, long *ioportset);
+long fli_camera_usb_write_ioport(flidev_t dev, long ioportset);
+long fli_camera_usb_configure_ioport(flidev_t dev, long ioportset);
+long fli_camera_usb_control_shutter(flidev_t dev, long shutter);
+long fli_camera_usb_control_bgflush(flidev_t dev, long bgflush);
+
+#endif /* _LIBFLI_CAMERA_USB_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-camera.c b/kstars/kstars/indi/fli/libfli-camera.c
new file mode 100644
index 00000000..369b0038
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-camera.c
@@ -0,0 +1,790 @@
+/*
+
+ 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
+
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include "libfli-libfli.h"
+#include "libfli-debug.h"
+#include "libfli-mem.h"
+#include "libfli-camera.h"
+#include "libfli-camera-parport.h"
+#include "libfli-camera-usb.h"
+
+const fliccdinfo_t knowndev[] = {
+ /* id model array_area visible_area */
+ {1, "KAF-0260C0-2", {{0, 0}, {534, 520}}, {{12, 4}, {524, 516}}, 1.0, 20.0, 20.0},
+ {2, "KAF-0400C0-2", {{0, 0}, {796, 520}}, {{14, 4}, {782, 516}}, 1.0, 20.0, 20.0},
+ {3, "KAF-1000C0-2", {{0, 0}, {1042, 1032}}, {{8, 4}, {1032, 1028}}, 1.0, 24.0, 24.0},
+ {4, "KAF-1300C0-2", {{0, 0}, {1304, 1028}}, {{4, 2}, {1284, 1026}}, 1.0, 20.0, 20.0},
+ {5, "KAF-1400C0-2", {{0, 0}, {1348, 1037}}, {{14,14}, {782, 526}}, 1.0, 20.0, 20.0},
+ {6, "KAF-1600C0-2", {{0, 0}, {1564, 1032}}, {{14, 4}, {1550, 1028}}, 1.0, 20.0, 20.0},
+ {7, "KAF-4200C0-2", {{0, 0}, {2060, 2048}}, {{25, 2}, {2057, 2046}}, 1.0, 20.0, 20.0},
+ {8, "SITe-502S", {{0, 0}, {527, 512}}, {{15, 0}, {527, 512}}, 1.0, 20.0, 20.0},
+ {9, "TK-1024", {{0, 0}, {1124, 1024}}, {{50, 0}, {1074, 1024}}, 1.0, 24.0, 24.0},
+ {10, "TK-512", {{0, 0}, {563, 512}}, {{51, 0}, {563, 512}}, 1.0, 24.0, 24.0},
+ {11, "SI-003A", {{0, 0}, {1056, 1024}}, {{16, 0}, {1040, 1024}}, 1.0, 24.0, 24.0},
+ {12, "KAF-6300", {{0, 0}, {3100, 2056}}, {{16, 4}, {3088, 2052}}, 1.0, 9.0, 9.0},
+ {13, "KAF-3200", {{0, 0}, {2267, 1510}}, {{46,34}, {2230, 1506}}, 1.0, 6.8, 6.8},
+ {14, "SI424A", {{0, 0}, {2088, 2049}}, {{20, 0}, {2068, 2049}}, 1.0, 6.8, 6.8},
+ {15, "CCD47-10", {{0, 0}, {1072, 1027}}, {{8, 0}, {1064, 1027}}, 0.0, 0.0, 0.0},
+ {16, "CCD77", {{0, 0}, {527, 512}}, {{15, 0}, {527, 512}}, 0.0, 0.0, 0.0},
+ {17, "CCD42-40", {{0, 0}, {2148, 2048}}, {{50, 0}, {2098, 2048}}, 1.0, 13.5, 13.5},
+ {18, "KAF-4300", {{0, 0}, {2102, 2092}}, {{8, 4}, {2092, 2088}}, 1.0, 24.0, 24.0},
+ {19, "KAF-16801", {{0, 0}, {4145, 4128}}, {{44,29}, {4124, 4109}}, 1.0, 9.0, 9.0},
+ {0, "Unknown Model", {{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, 0.0, 0.0, 0.0}
+};
+
+/* Common camera routines */
+static long fli_camera_get_pixel_size(flidev_t dev,
+ double *pixel_x, double *pixel_y);
+#define fli_camera_parport_get_pixel_size fli_camera_get_pixel_size
+#define fli_camera_usb_get_pixel_size fli_camera_get_pixel_size
+
+static long fli_camera_set_frame_type(flidev_t dev, fliframe_t frametype);
+#define fli_camera_parport_set_frame_type fli_camera_set_frame_type
+#define fli_camera_usb_set_frame_type fli_camera_set_frame_type
+
+static long fli_camera_set_flushes(flidev_t dev, long nflushes);
+#define fli_camera_parport_set_flushes fli_camera_set_flushes
+#define fli_camera_usb_set_flushes fli_camera_set_flushes
+
+long fli_camera_open(flidev_t dev)
+{
+ int r;
+
+ CHKDEVICE(dev);
+
+ if ((DEVICE->device_data = xcalloc(1, sizeof(flicamdata_t))) == NULL)
+ return -ENOMEM;
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_open(dev);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_open(dev);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+
+ if (r)
+ {
+ xfree(DEVICE->device_data);
+ DEVICE->device_data = NULL;
+ }
+
+ return r;
+}
+
+long fli_camera_close(flidev_t dev)
+{
+ flicamdata_t *cam;
+
+ CHKDEVICE(dev);
+
+ cam = DEVICE->device_data;
+
+ if (cam->gbuf != NULL)
+ {
+ xfree(cam->gbuf);
+ cam->gbuf = NULL;
+ }
+
+ if (DEVICE->devinfo.model != NULL)
+ {
+ xfree(DEVICE->devinfo.model);
+ DEVICE->devinfo.model = NULL;
+ }
+
+ if (DEVICE->devinfo.devnam != NULL)
+ {
+ xfree(DEVICE->devinfo.devnam);
+ DEVICE->devinfo.devnam = NULL;
+ }
+
+ if (DEVICE->device_data != NULL)
+ {
+ xfree(DEVICE->device_data);
+ DEVICE->device_data = NULL;
+ }
+
+ return 0;
+}
+
+long fli_camera_command(flidev_t dev, int cmd, int argc, ...)
+{
+ long r;
+ va_list ap;
+
+ va_start(ap, argc);
+ CHKDEVICE(dev);
+
+ switch (cmd)
+ {
+ case FLI_GET_PIXEL_SIZE:
+ if (argc != 2)
+ r = -EINVAL;
+ else
+ {
+ double *pixel_x, *pixel_y;
+
+ pixel_x = va_arg(ap, double *);
+ pixel_y = va_arg(ap, double *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_get_pixel_size(dev, pixel_x, pixel_y);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_get_pixel_size(dev, pixel_x, pixel_y);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_GET_ARRAY_AREA:
+ if (argc != 4)
+ r = -EINVAL;
+ else
+ {
+ long *ul_x, *ul_y, *lr_x, *lr_y;
+
+ ul_x = va_arg(ap, long *);
+ ul_y = va_arg(ap, long *);
+ lr_x = va_arg(ap, long *);
+ lr_y = va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_get_array_area(dev, ul_x, ul_y, lr_x, lr_y);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_get_array_area(dev, ul_x, ul_y, lr_x, lr_y);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_GET_VISIBLE_AREA:
+ if (argc != 4)
+ r = -EINVAL;
+ else
+ {
+ long *ul_x, *ul_y, *lr_x, *lr_y;
+
+ ul_x = va_arg(ap, long *);
+ ul_y = va_arg(ap, long *);
+ lr_x = va_arg(ap, long *);
+ lr_y = va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_get_visible_area(dev, ul_x, ul_y, lr_x, lr_y);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_get_visible_area(dev, ul_x, ul_y, lr_x, lr_y);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_EXPOSURE_TIME:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long exptime;
+
+ exptime = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_exposure_time(dev, exptime);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_exposure_time(dev, exptime);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_IMAGE_AREA:
+ if (argc != 4)
+ r = -EINVAL;
+ else
+ {
+ long ul_x, ul_y, lr_x, lr_y;
+
+ ul_x = *va_arg(ap, long *);
+ ul_y = *va_arg(ap, long *);
+ lr_x = *va_arg(ap, long *);
+ lr_y = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_image_area(dev, ul_x, ul_y, lr_x, lr_y);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_image_area(dev, ul_x, ul_y, lr_x, lr_y);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_HBIN:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long hbin;
+
+ hbin = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_hbin(dev, hbin);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_hbin(dev, hbin);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_VBIN:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long vbin;
+
+ vbin = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_vbin(dev, vbin);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_vbin(dev, vbin);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_FRAME_TYPE:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long frametype;
+
+ frametype = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_frame_type(dev, frametype);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_frame_type(dev, frametype);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_CANCEL_EXPOSURE:
+ if (argc != 0)
+ r = -EINVAL;
+ else
+ {
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ cam->grabrowcount = 1;
+ cam->grabrowcounttot = cam->grabrowcount;
+ cam->grabrowindex = 0;
+ cam->grabrowbatchsize = 1;
+ cam->grabrowbufferindex = cam->grabrowcount;
+ cam->flushcountbeforefirstrow = 0;
+ cam->flushcountafterlastrow = 0;
+
+ r = DEVICE->fli_command(dev, FLI_CONTROL_SHUTTER, (long) FLI_SHUTTER_CLOSE);
+ }
+ break;
+
+ case FLI_GET_EXPOSURE_STATUS:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *timeleft;
+
+ timeleft = va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_get_exposure_status(dev, timeleft);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_get_exposure_status(dev, timeleft);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_TEMPERATURE:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ double temperature;
+
+ temperature = *va_arg(ap, double *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_temperature(dev, temperature);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_temperature(dev, temperature);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_GET_TEMPERATURE:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ double *temperature;
+
+ temperature = va_arg(ap, double *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_get_temperature(dev, temperature);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_get_temperature(dev, temperature);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_GRAB_ROW:
+ if (argc != 2)
+ r = -EINVAL;
+ else
+ {
+ void *buf;
+ size_t width;
+
+ buf = va_arg(ap, void *);
+ width = *va_arg(ap, size_t *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_grab_row(dev, buf, width);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_grab_row(dev, buf, width);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_EXPOSE_FRAME:
+ if (argc != 0)
+ r = -EINVAL;
+ else
+ {
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_expose_frame(dev);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_expose_frame(dev);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_FLUSH_ROWS:
+ if (argc != 2)
+ r = -EINVAL;
+ else
+ {
+ long rows, repeat;
+
+ rows = *va_arg(ap, long *);
+ repeat = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_flush_rows(dev, rows, repeat);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_flush_rows(dev, rows, repeat);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_FLUSHES:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long nflushes;
+
+ nflushes = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_flushes(dev, nflushes);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_flushes(dev, nflushes);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_SET_BIT_DEPTH:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ flibitdepth_t bitdepth;
+
+ bitdepth = *va_arg(ap, flibitdepth_t *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_set_bit_depth(dev, bitdepth);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_set_bit_depth(dev, bitdepth);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_READ_IOPORT:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *ioportset;
+
+ ioportset = va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_read_ioport(dev, ioportset);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_read_ioport(dev, ioportset);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_WRITE_IOPORT:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long ioportset;
+
+ ioportset = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_write_ioport(dev, ioportset);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_write_ioport(dev, ioportset);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_CONFIGURE_IOPORT:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long ioportset;
+
+ ioportset = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_configure_ioport(dev, ioportset);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_configure_ioport(dev, ioportset);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ case FLI_CONTROL_SHUTTER:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long shutter;
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ shutter = *va_arg(ap, long *);
+
+ if( (shutter == FLI_SHUTTER_EXTERNAL_TRIGGER_LOW) ||
+ (shutter == FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH) )
+ {
+ debug(FLIDEBUG_INFO, "External trigger.\n");
+ cam->exttrigger = 1;
+ cam->exttriggerpol = (shutter == FLI_SHUTTER_EXTERNAL_TRIGGER_LOW)?0:1;
+ r = 0;
+ }
+ else
+ {
+ cam->exttrigger = 0;
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = fli_camera_parport_control_shutter(dev, shutter);
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_control_shutter(dev, shutter);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ }
+ break;
+
+ case FLI_CONTROL_BGFLUSH:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long bgflush;
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ bgflush = *va_arg(ap, long *);
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ r = -EFAULT;
+ break;
+
+ case FLIDOMAIN_USB:
+ r = fli_camera_usb_control_bgflush(dev, bgflush);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+ }
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+
+ va_end(ap);
+
+ return r;
+}
+
+static long fli_camera_get_pixel_size(flidev_t dev,
+ double *pixel_x, double *pixel_y)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+ *pixel_x = (double)cam->ccd.pixelwidth;
+ *pixel_y = (double)cam->ccd.pixelheight;
+
+ return 0;
+}
+
+static long fli_camera_set_frame_type(flidev_t dev, fliframe_t frametype)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if ((frametype < FLI_FRAME_TYPE_NORMAL) || (frametype > FLI_FRAME_TYPE_DARK))
+ return -EINVAL;
+
+ cam->frametype = frametype;
+
+ return 0;
+}
+
+static long fli_camera_set_flushes(flidev_t dev, long nflushes)
+{
+ flicamdata_t *cam;
+
+ cam = DEVICE->device_data;
+
+ if((nflushes < 0) || (nflushes > 5))
+ return -EINVAL;
+
+ cam->flushes = nflushes;
+
+ return 0;
+}
diff --git a/kstars/kstars/indi/fli/libfli-camera.h b/kstars/kstars/indi/fli/libfli-camera.h
new file mode 100644
index 00000000..2d4f2b99
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-camera.h
@@ -0,0 +1,111 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_CAMERA_H_
+#define _LIBFLI_CAMERA_H_
+
+typedef struct {
+ int x; /* X coordinate */
+ int y; /* Y coordinate */
+} point_t;
+
+typedef struct {
+ point_t ul; /* Upper-left */
+ point_t lr; /* Lower-right */
+} area_t;
+
+/* CCD Parameter list */
+typedef struct
+{
+ short index;
+ const char *model;
+ area_t array_area;
+ area_t visible_area;
+ double fillfactor;
+ double pixelwidth;
+ double pixelheight;
+} fliccdinfo_t;
+
+typedef struct {
+ long readto;
+ long writeto;
+ long dirto;
+ fliccdinfo_t ccd;
+
+ /* Acquisistion parameters */
+ area_t image_area;
+ long vbin;
+ long hbin;
+ long vflushbin;
+ long hflushbin;
+ long exposure;
+ long expdur;
+ long expmul;
+ long frametype;
+ long flushes;
+ long bitdepth;
+ long exttrigger;
+ long exttriggerpol;
+
+ double tempslope;
+ double tempintercept;
+
+ long grabrowcount;
+ long grabrowcounttot;
+ long grabrowindex;
+ long grabrowwidth;
+ long grabrowbatchsize;
+ long grabrowbufferindex;
+ long flushcountbeforefirstrow;
+ long flushcountafterlastrow;
+
+ unsigned short *gbuf;
+} flicamdata_t;
+
+extern const fliccdinfo_t knowndev[];
+
+long fli_camera_open(flidev_t dev);
+long fli_camera_close(flidev_t dev);
+long fli_camera_command(flidev_t dev, int cmd, int argc, ...);
+
+#endif /* _LIBFLI_CAMERA_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-debug.c b/kstars/kstars/indi/fli/libfli-debug.c
new file mode 100644
index 00000000..203274b3
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-debug.c
@@ -0,0 +1,120 @@
+/*
+
+ 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
+
+*/
+
+#include <syslog.h>
+#include <stdarg.h>
+
+#include "libfli-libfli.h"
+
+int sysloglevel(int level)
+{
+ switch (level)
+ {
+ case FLIDEBUG_INFO:
+ return LOG_INFO;
+ break;
+
+ case FLIDEBUG_WARN:
+ return LOG_WARNING;
+ break;
+
+ case FLIDEBUG_FAIL:
+ return LOG_ERR;
+ break;
+
+ case FLIDEBUG_ALL:
+ return LOG_EMERG | LOG_ALERT | LOG_CRIT | LOG_ERR | LOG_WARNING |
+ LOG_NOTICE | LOG_INFO | LOG_DEBUG;
+ break;
+ }
+
+ return 0;
+}
+
+int debugopen(char *host)
+{
+ openlog("libfli", LOG_PID , LOG_USER);
+
+ return 0;
+}
+
+int debugclose(void)
+{
+ closelog();
+
+ return 0;
+}
+
+void debug(int level, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vsyslog(sysloglevel(level), format, ap);
+ va_end(ap);
+
+ return;
+}
+
+
+void setdebuglevel(char *host, int level)
+{
+ static int open = 0;
+
+ if (level == 0)
+ {
+ debugclose();
+ open = 0;
+ return;
+ }
+
+ if (open == 0)
+ {
+ debugopen(host);
+ open = 1;
+ }
+
+ setlogmask(LOG_UPTO(sysloglevel(level)));
+
+ return;
+}
diff --git a/kstars/kstars/indi/fli/libfli-debug.h b/kstars/kstars/indi/fli/libfli-debug.h
new file mode 100644
index 00000000..775244ae
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-debug.h
@@ -0,0 +1,53 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_DEBUG_H_
+#define _LIBFLI_DEBUG_H_
+
+/* Debug functions */
+int debugclose(void);
+int debugopen(char *host);
+void debug(int level, const char *format, ...);
+void setdebuglevel(char *host, int level);
+
+#endif /* _LIBFLI_DEBUG_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-filter-focuser.c b/kstars/kstars/indi/fli/libfli-filter-focuser.c
new file mode 100644
index 00000000..ef4afb8e
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-filter-focuser.c
@@ -0,0 +1,625 @@
+/*
+
+ 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 <stdlib.h>
+#include <time.h>
+#include <stdarg.h>
+
+#include "libfli-libfli.h"
+#include "libfli-mem.h"
+#include "libfli-debug.h"
+#include "libfli-filter-focuser.h"
+
+/*
+Array of filterwheel info
+ Pos = # of filters
+ Off = Offset of 0 filter from magnetic stop,
+ X - y = number of steps from filter x to filter y
+*/
+static const wheeldata_t wheeldata[] =
+{
+ /* POS OFF 0-1 1-2 2-3 3-4 4-5 5-6 6-7 7-8 8-9 9-A A-B B-C C-D D-E F-F F-0 */
+ { 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 1, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 2, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 3, 48, { 80, 80, 80, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 4, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 5, 0, { 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 6, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 7, 14, { 34, 34, 35, 34, 34, 35, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 8, 18, { 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0} },
+ { 9, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {10, 0, { 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0} },
+ {11, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {12, 6,{ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0} },
+ {13, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {14, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+ {15, 0, { 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48} },
+};
+
+static long fli_stepmotor(flidev_t dev, long steps);
+static long fli_getsteppos(flidev_t dev, long *pos);
+static long fli_setfilterpos(flidev_t dev, long pos);
+
+
+long fli_filter_focuser_open(flidev_t dev)
+{
+#define FWSTRING "Filter Wheel (%ld position)"
+#define FOCSTRING "Focuser"
+#define MODEL_LEN (sizeof(FWSTRING) + 30)
+ int err = 0;
+ unsigned long ndev;
+ long rlen, wlen;
+ unsigned short buf[16];
+ flifilterdata_t *fdata = NULL;
+
+ CHKDEVICE(dev);
+
+ DEVICE->io_timeout = 1000;
+
+ wlen = 2;
+ rlen = 2;
+ buf[0] = htons(0x8000);
+ IO(dev, buf, &wlen, &rlen);
+ if (ntohs(buf[0]) != 0x8000)
+ {
+ debug(FLIDEBUG_WARN, "Invalid echo, device not recognized, got %04x instead of %04x.", ntohs(buf[0]), 0x8000);
+ err = -ENODEV;
+ goto done;
+ }
+
+ wlen = 2;
+ rlen = 2;
+ buf[0] = htons(0x8001);
+ IO(dev, buf, &wlen, &rlen);
+ DEVICE->devinfo.fwrev = ntohs(buf[0]);
+ if ((DEVICE->devinfo.fwrev & 0xff00) != 0x8000)
+ {
+ debug(FLIDEBUG_WARN, "Invalid echo, device not recognized.");
+ err = -ENODEV;
+ goto done;
+ }
+
+ if ((DEVICE->device_data = xmalloc(sizeof(flifilterdata_t))) == NULL)
+ {
+ err = -ENOMEM;
+ goto done;
+ }
+ fdata = DEVICE->device_data;
+ fdata->numslots = 0;
+ fdata->stepspersec = 100;
+ fdata->currentslot = -1;
+
+ if (DEVICE->devinfo.fwrev == 0x8001) /* Old level of firmware */
+ {
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+
+ debug(FLIDEBUG_INFO, "Device is old fashioned filter wheel.");
+ fdata->numslots = 5;
+
+ /* FIX: should model info be set first? */
+ return 0;
+ }
+
+ debug(FLIDEBUG_INFO, "New version of hardware found.");
+ wlen = 2;
+ rlen = 2;
+ buf[0] = htons(0x8002);
+ IO(dev, buf, &wlen, &rlen);
+ ndev = ntohs(buf[0]);
+
+ if ((ndev & 0xff00) != 0x8000)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+
+ if ((DEVICE->devinfo.model = (char *)xmalloc(MODEL_LEN)) == NULL)
+ {
+ debug(FLIDEBUG_FAIL, "Could not allocate memory for model information.");
+ err = -ENOMEM;
+ goto done;
+ }
+
+ ndev &= 0x00ff;
+
+ /* switch based on the jumper settings on the filter/focuser dongle, determines how many slots in the filter wheel */
+ switch (ndev)
+ {
+ case 0x00:
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ fdata->numslots = 5;
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+ case 0x01:
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ fdata->numslots = 3;
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+ case 0x02:
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ fdata->numslots = 7;
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+ case 0x03:
+ fdata->numslots = 8;
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+ case 0x04:
+ fdata->numslots = 15;
+ fdata->stepspersec= 16;/* // 1/.06 */
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+
+ case 0x05:
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ fdata->numslots = 12;
+ fdata->stepspersec= 16; /*// 1/.06*/
+
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+ case 0x06:
+ fdata->numslots = 10;
+ fdata->stepspersec= 16; /*// 1/.06*/
+ if (DEVICE->devinfo.type != FLIDEVICE_FILTERWHEEL)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FWSTRING, fdata->numslots);
+ break;
+
+
+ case 0x07:
+ if (DEVICE->devinfo.type != FLIDEVICE_FOCUSER)
+ {
+ err = -ENODEV;
+ goto done;
+ }
+ snprintf(DEVICE->devinfo.model, MODEL_LEN, FOCSTRING);
+ break;
+
+ default:
+ err = -ENODEV;
+ goto done;
+ }
+
+ done:
+
+ if (err)
+ {
+ if (DEVICE->devinfo.model != NULL)
+ {
+ xfree(DEVICE->devinfo.model);
+ DEVICE->devinfo.model = NULL;
+ }
+
+ if (DEVICE->device_data != NULL)
+ {
+ xfree(DEVICE->device_data);
+ DEVICE->device_data = NULL;
+ }
+
+ return err;
+ }
+
+ debug(FLIDEBUG_INFO, "Found a %ld slot filter wheel or a focuser.",
+ fdata->numslots);
+
+#undef FWSTRING
+#undef FOCSTRING
+#undef MODEL_LEN
+
+ return 0;
+}
+
+long fli_filter_focuser_close(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ if (DEVICE->devinfo.model != NULL)
+ {
+ xfree(DEVICE->devinfo.model);
+ DEVICE->devinfo.model = NULL;
+ }
+
+ if (DEVICE->device_data != NULL)
+ {
+ xfree(DEVICE->device_data);
+ DEVICE->device_data = NULL;
+ }
+
+ return 0;
+}
+
+long fli_filter_command(flidev_t dev, int cmd, int argc, ...)
+{
+ flifilterdata_t *fdata;
+ long r;
+ va_list ap;
+
+ va_start(ap, argc);
+ CHKDEVICE(dev);
+ fdata = DEVICE->device_data;
+
+ switch (cmd)
+ {
+ case FLI_SET_FILTER_POS:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long pos;
+
+ pos = *va_arg(ap, long *);
+ r = fli_setfilterpos(dev, pos);
+ }
+ break;
+
+ case FLI_GET_FILTER_POS:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *cslot;
+
+ cslot = va_arg(ap, long *);
+ *cslot = fdata->currentslot;
+ r = 0;
+ }
+ break;
+
+ case FLI_GET_FILTER_COUNT:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *nslots;
+
+ nslots = va_arg(ap, long *);
+ *nslots = fdata->numslots;
+ r = 0;
+ }
+ break;
+
+ case FLI_STEP_MOTOR:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *steps;
+
+ steps = va_arg(ap, long *);
+ r = fli_stepmotor(dev, *steps);
+ }
+ break;
+
+ case FLI_GET_STEPPER_POS:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *pos;
+
+ pos = va_arg(ap, long *);
+ r = fli_getsteppos(dev, pos);
+ }
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+
+ va_end(ap);
+
+ return r;
+}
+
+long fli_focuser_command(flidev_t dev, int cmd, int argc, ...)
+{
+ long r;
+ va_list ap;
+
+ va_start(ap, argc);
+ CHKDEVICE(dev);
+
+ switch (cmd)
+ {
+ case FLI_STEP_MOTOR:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *steps;
+
+ steps = va_arg(ap, long *);
+ r = fli_stepmotor(dev, *steps);
+ }
+ break;
+
+ case FLI_GET_STEPPER_POS:
+ if (argc != 1)
+ r = -EINVAL;
+ else
+ {
+ long *pos;
+
+ pos = va_arg(ap, long *);
+ r = fli_getsteppos(dev, pos);
+ }
+ break;
+
+ case FLI_HOME_FOCUSER:
+ if (argc != 0)
+ r = -EINVAL;
+ else
+ r = fli_setfilterpos(dev, FLI_FILTERPOSITION_HOME);
+ break;
+
+ default:
+ r = -EINVAL;
+ }
+
+ va_end(ap);
+
+ return r;
+}
+
+static long fli_stepmotor(flidev_t dev, long steps)
+{
+ flifilterdata_t *fdata;
+ long dir, timeout, move, stepsleft;
+ long rlen,wlen;
+ unsigned short buf[16];
+ clock_t begin;
+
+ if (steps == 0)
+ return 0;
+
+ fdata = DEVICE->device_data;
+
+ dir = steps;
+ steps = abs(steps);
+ while (steps > 0)
+ {
+ if (steps > 2048)
+ move = 2048;
+ else
+ move = steps;
+
+ debug(FLIDEBUG_INFO, "Stepping %d steps.", move);
+
+ steps -= move;
+ timeout = (move / fdata->stepspersec) + 2;
+
+ rlen = 2;
+ wlen = 2;
+ if (dir < 0)
+ {
+ buf[0] = htons((unsigned short) (0xa000 | (unsigned short) move));
+ IO(dev, buf, &wlen, &rlen);
+ if ((ntohs(buf[0]) & 0xf000) != 0xa000)
+ {
+ debug(FLIDEBUG_WARN, "Invalid echo.");
+ return -EIO;
+ }
+ }
+ else
+ {
+ buf[0] = htons((unsigned short) (0x9000 | (unsigned short) move));
+ IO(dev, buf, &wlen, &rlen);
+ if ((ntohs(buf[0]) & 0xf000) != 0x9000)
+ {
+ debug(FLIDEBUG_WARN, "Invalid echo.");
+ return -EIO;
+ }
+ }
+
+ begin = clock();
+ stepsleft = 0;
+ while (stepsleft != 0x7000)
+ {
+ buf[0] = htons(0x7000);
+ IO(dev, buf, &wlen, &rlen);
+ stepsleft = ntohs(buf[0]);
+
+ if (((clock() - begin) / CLOCKS_PER_SEC) > timeout)
+ {
+ debug(FLIDEBUG_WARN, "A device timeout has occurred.");
+ return -EIO;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static long fli_getsteppos(flidev_t dev, long *pos)
+{
+ long poslow, poshigh;
+ long rlen, wlen;
+ unsigned short buf[16];
+
+ rlen = 2; wlen = 2;
+ buf[0] = htons(0x6000);
+ IO(dev, buf, &wlen, &rlen);
+ poslow = ntohs(buf[0]);
+ if ((poslow & 0xf000) != 0x6000)
+ return -EIO;
+
+ buf[0] = htons(0x6001);
+ IO(dev, buf, &wlen, &rlen);
+ poshigh = ntohs(buf[0]);
+ if ((poshigh & 0xf000) != 0x6000)
+ return -EIO;
+
+ if ((poshigh & 0x0080) > 0)
+ {
+ *pos = ((~poslow) & 0xff) + 1;
+ *pos += (256 * ((~poshigh) & 0xff));
+ *pos = -(*pos);
+ }
+ else
+ {
+ *pos = (poslow & 0xff) + 256 * (poshigh & 0xff);
+ }
+ return 0;
+}
+
+
+static long fli_setfilterpos(flidev_t dev, long pos)
+{
+ flifilterdata_t *fdata;
+ long rlen, wlen;
+ unsigned short buf[16];
+ long move, i, steps;
+
+ fdata = DEVICE->device_data;
+
+ if (pos == FLI_FILTERPOSITION_HOME)
+ fdata->currentslot = FLI_FILTERPOSITION_HOME;
+
+ if (fdata->currentslot < 0)
+ {
+ debug(FLIDEBUG_INFO, "Home filter wheel/focuser.");
+ /* //set the timeout*/
+ DEVICE->io_timeout = (DEVICE->devinfo.type == FLIDEVICE_FILTERWHEEL ? 5000 : 30000);
+ /*//10,12,15 pos filterwheel needs a longer timeout t*/
+ if(fdata->numslots == 12||fdata->numslots == 10)
+ {
+ DEVICE->io_timeout = 120000;
+ }
+ if(fdata->numslots == 15)
+ {
+ DEVICE->io_timeout = 200000;
+ }
+
+ wlen = 2;
+ rlen = 2;
+ buf[0] = htons(0xf000);
+ IO(dev, buf, &wlen, &rlen);
+ if (ntohs(buf[0]) != 0xf000)
+ return -EIO;
+
+ DEVICE->io_timeout = 1000;
+
+ debug(FLIDEBUG_INFO, "Moving %d steps to home position.",
+ wheeldata[fdata->numslots].n_offset);
+
+ COMMAND(fli_stepmotor(dev, - (wheeldata[fdata->numslots].n_offset)));
+ fdata->currentslot = 0;
+ }
+
+ if (pos == FLI_FILTERPOSITION_HOME)
+ return 0;
+
+ if (pos >= fdata->numslots)
+ {
+ debug(FLIDEBUG_WARN, "Requested slot (%d) exceeds number of slots.", pos);
+ return -EINVAL;
+ }
+
+ if (pos == fdata->currentslot)
+ return 0;
+
+ move = pos - fdata->currentslot;
+
+ if (move < 0)
+ move += fdata->numslots;
+
+ steps = 0;
+ for (i=0; i < move; i++)
+ steps += wheeldata[fdata->numslots].n_steps[i % fdata->numslots];
+
+ debug(FLIDEBUG_INFO, "Move filter wheel %d steps.", steps);
+
+ COMMAND(fli_stepmotor(dev, - (steps)));
+ fdata->currentslot = pos;
+
+ return 0;
+}
diff --git a/kstars/kstars/indi/fli/libfli-filter-focuser.h b/kstars/kstars/indi/fli/libfli-filter-focuser.h
new file mode 100644
index 00000000..dc50e4e9
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-filter-focuser.h
@@ -0,0 +1,74 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _FLI_FILTER_FOCUSER_H_
+#define _FLI_FILTER_FOCUSER_H_
+
+#define FLI_FILTERPOSITION_HOME (-1)
+
+/* Filter wheel and focuser parameters */
+typedef struct {
+ long numslots;
+ long stepspersec;
+ long currentslot;
+} flifilterdata_t;
+
+typedef struct {
+ int n_pos;
+ int n_offset;
+ int n_steps[16];
+} wheeldata_t;
+
+long fli_filter_focuser_open(flidev_t dev);
+#define fli_filter_open fli_filter_focuser_open
+#define fli_focuser_open fli_filter_focuser_open
+
+long fli_filter_focuser_close(flidev_t dev);
+#define fli_filter_close fli_filter_focuser_close
+#define fli_focuser_close fli_filter_focuser_close
+
+long fli_filter_command(flidev_t dev, int cmd, int argc, ...);
+long fli_focuser_command(flidev_t dev, int cmd, int argc, ...);
+
+
+#endif /* _FLI_FILTER_FOCUSER_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-libfli.h b/kstars/kstars/indi/fli/libfli-libfli.h
new file mode 100644
index 00000000..1a497d1d
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-libfli.h
@@ -0,0 +1,199 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_LIBFLI_H_
+#define _LIBFLI_LIBFLI_H_
+
+#include <string.h>
+
+#ifdef WIN32
+#define LIBFLIAPI __declspec(dllexport) long __stdcall
+#endif
+
+#include "libfli.h"
+#include "libfli-sys.h"
+#include "libfli-debug.h"
+
+#define __STRINGIFY(x) ___STRINGIFY(x)
+#define ___STRINGIFY(x) #x
+
+#define __LIBFLIVER_MAJOR__ 1
+#define __LIBFLIVER__ __STRINGIFY(__LIBFLIVER_MAJOR__) "." \
+ __STRINGIFY(__LIBFLI_MINOR__)
+
+#define CHKDEVICE(xdev) \
+ do { \
+ if((xdev < 0) || (xdev >= MAX_OPEN_DEVICES)) \
+ { \
+ debug(FLIDEBUG_WARN, \
+ "Attempt to use a device out of range (%d)", xdev); \
+ return -EINVAL; \
+ } \
+ if(devices[xdev] == NULL) \
+ { \
+ debug(FLIDEBUG_WARN, \
+ "Attempt to use a NULL device (%d)", xdev); \
+ return -EINVAL; \
+ } \
+ } while(0)
+
+#define CHKFUNCTION(func) \
+ do { \
+ if(func == NULL) \
+ { \
+ debug(FLIDEBUG_WARN, \
+ "Attempt to use a NULL function (" #func ")"); \
+ return -EINVAL; \
+ } \
+ } while(0)
+
+#define IO(dev, buf, wlen, rlen) \
+ do { \
+ int err; \
+ if((err = devices[dev]->fli_io(dev, buf, wlen, rlen))) \
+ { \
+ debug(FLIDEBUG_WARN, "Communication error: %d [%s]", \
+ err, strerror(-err)); \
+ return err; \
+ } \
+ } while(0)
+
+#define COMMAND(function) \
+ do { \
+ int err; \
+ if((err = function)) \
+ { \
+ debug(FLIDEBUG_WARN, \
+ "Function `" #function "' failed, error: %d [%s]", \
+ err, strerror(-err)); \
+ return err; \
+ } \
+ } while(0)
+
+#define FLIUSB_VENDORID 0xf18
+#define FLIUSB_CAM_ID 0x02
+#define FLIUSB_FILTER_ID 0x07
+#define FLIUSB_FOCUSER_ID 0x06
+
+#define MAX_OPEN_DEVICES (32)
+#define MAX_SEARCH_LIST (16)
+
+/* Common device information */
+typedef struct {
+ long type;
+ long fwrev;
+ long hwrev;
+ long devid;
+ long serno;
+ char *model;
+ char *devnam;
+} flidevinfo_t;
+
+/* A specific device instance */
+typedef struct {
+ char *name; /* The device name */
+ long domain; /* The device's domain */
+ flidevinfo_t devinfo; /* Device information */
+ long io_timeout; /* Timeout in msec for all I/O */
+ void *io_data; /* For holding I/O specific data */
+ void *device_data; /* For holding device specific data */
+ void *sys_data; /* For holding system specific data */
+
+ /* System-specific functions */
+ long (*fli_lock)(flidev_t dev);
+ long (*fli_unlock)(flidev_t dev);
+
+ /* Domain-specific functions */
+ long (*fli_io)(flidev_t dev, void *buf, long *wlen, long *rlen);
+
+ /* Device-specific functions */
+ long (*fli_open)(flidev_t dev);
+ long (*fli_close)(flidev_t dev);
+ long (*fli_command)(flidev_t dev, int cmd, int argc, ...);
+} flidevdesc_t;
+
+extern const char* version;
+
+extern flidevdesc_t *devices[MAX_OPEN_DEVICES];
+#define DEVICE devices[dev]
+
+/* Device commands, the format is FLI_COMMAND(<command name>, <number of args>) */
+#define FLI_COMMANDS \
+ FLI_COMMAND(FLI_NONE, 0) \
+ FLI_COMMAND(FLI_GET_PIXEL_SIZE, 2) \
+ FLI_COMMAND(FLI_GET_ARRAY_AREA, 4) \
+ FLI_COMMAND(FLI_GET_VISIBLE_AREA, 4) \
+ FLI_COMMAND(FLI_SET_EXPOSURE_TIME, 1) \
+ FLI_COMMAND(FLI_SET_IMAGE_AREA, 4) \
+ FLI_COMMAND(FLI_SET_HBIN, 1) \
+ FLI_COMMAND(FLI_SET_VBIN, 1) \
+ FLI_COMMAND(FLI_SET_FRAME_TYPE, 1) \
+ FLI_COMMAND(FLI_CANCEL_EXPOSURE, 0) \
+ FLI_COMMAND(FLI_GET_EXPOSURE_STATUS, 1) \
+ FLI_COMMAND(FLI_SET_TEMPERATURE, 1) \
+ FLI_COMMAND(FLI_GET_TEMPERATURE, 1) \
+ FLI_COMMAND(FLI_GRAB_ROW, 2) \
+ FLI_COMMAND(FLI_EXPOSE_FRAME, 0) \
+ FLI_COMMAND(FLI_FLUSH_ROWS, 2) \
+ FLI_COMMAND(FLI_SET_FLUSHES, 1) \
+ FLI_COMMAND(FLI_SET_BIT_DEPTH, 1) \
+ FLI_COMMAND(FLI_READ_IOPORT, 1) \
+ FLI_COMMAND(FLI_WRITE_IOPORT, 1) \
+ FLI_COMMAND(FLI_CONFIGURE_IOPORT, 1) \
+ FLI_COMMAND(FLI_CONTROL_SHUTTER, 1) \
+ FLI_COMMAND(FLI_CONTROL_BGFLUSH, 1) \
+ FLI_COMMAND(FLI_SET_FILTER_POS, 1) \
+ FLI_COMMAND(FLI_GET_FILTER_POS, 1) \
+ FLI_COMMAND(FLI_GET_FILTER_COUNT, 1) \
+ FLI_COMMAND(FLI_STEP_MOTOR, 1) \
+ FLI_COMMAND(FLI_GET_STEPPER_POS, 1) \
+ FLI_COMMAND(FLI_HOME_FOCUSER, 0)
+
+/* Enumerate the commands */
+enum {
+#define FLI_COMMAND(name, args) name,
+ FLI_COMMANDS
+#undef FLI_COMMAND
+};
+
+#endif /* _LIBFLI_LIBFLI_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-mem.c b/kstars/kstars/indi/fli/libfli-mem.c
new file mode 100644
index 00000000..f6bee1bc
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-mem.c
@@ -0,0 +1,203 @@
+/*
+
+ Copyright (c) 2000, 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
+
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "libfli-libfli.h"
+#include "libfli-mem.h"
+
+#define DEFAULT_NUM_POINTERS (1024)
+
+static struct {
+ void **pointers;
+ int total;
+ int used;
+} allocated = {NULL, 0, 0};
+
+void *xmalloc(size_t size)
+{
+ int i;
+ void *ptr;
+
+ if (allocated.used + 1 > allocated.total)
+ {
+ void **tmp;
+ int num;
+
+ num = (allocated.total == 0 ? DEFAULT_NUM_POINTERS : 2 * allocated.total);
+
+ if ((tmp = (void **)realloc(allocated.pointers,
+ num * sizeof(void **))) == NULL)
+ return NULL;
+
+ allocated.pointers = tmp;
+ memset(&allocated.pointers[allocated.total], 0, num * sizeof(void **));
+ allocated.total += num;
+ }
+
+ if ((ptr = malloc(size)) == NULL)
+ return NULL;
+
+ for (i = 0; i < allocated.total; i++)
+ {
+ if (allocated.pointers[i] == NULL)
+ break;
+ }
+
+ if (i == allocated.total)
+ {
+ /* This shouldn't happen */
+ debug(FLIDEBUG_WARN, "Internal memory allocation error");
+ free(ptr);
+
+ return NULL;
+ }
+
+ allocated.pointers[i] = ptr;
+ allocated.used++;
+
+ return ptr;
+}
+
+
+void *xcalloc(size_t nmemb, size_t size)
+{
+ void *ptr;
+
+ if ((ptr = xmalloc(nmemb * size)) == NULL)
+ return NULL;
+
+ memset(ptr, 0, nmemb * size);
+
+ return ptr;
+}
+
+void xfree(void *ptr)
+{
+ int i;
+
+ for (i = 0; i < allocated.total; i++)
+ {
+ if (allocated.pointers[i] == ptr)
+ {
+ free(ptr);
+ allocated.pointers[i] = NULL;
+ allocated.used--;
+
+ return;
+ }
+ }
+
+ debug(FLIDEBUG_WARN, "Attempting to free an invalid pointer");
+
+ return;
+}
+
+void *xrealloc(void *ptr, size_t size)
+{
+ int i;
+
+ for (i = 0; i < allocated.total; i++)
+ {
+ if (allocated.pointers[i] == ptr)
+ {
+ void *tmp;
+
+ if ((tmp = realloc(ptr, size)) == NULL)
+ return NULL;
+
+ allocated.pointers[i] = tmp;
+
+ return tmp;
+ }
+ }
+
+ debug(FLIDEBUG_WARN, "Attempting to realloc an invalid pointer");
+
+ return NULL;
+}
+
+int xfree_all(void)
+{
+ int i;
+ int freed = 0;
+
+ for (i = 0; i < allocated.total; i++)
+ {
+ if (allocated.pointers[i] != NULL)
+ {
+ free(allocated.pointers[i]);
+ allocated.pointers[i] = NULL;
+ allocated.used--;
+ freed++;
+ }
+ }
+
+ if (allocated.used != 0)
+ debug(FLIDEBUG_WARN, "Internal memory handling error");
+
+ if (allocated.pointers != NULL)
+ free(allocated.pointers);
+
+ allocated.pointers = NULL;
+ allocated.used = 0;
+ allocated.total = 0;
+
+ return freed;
+}
+
+char *xstrdup(const char *s)
+{
+ void *tmp;
+ size_t len;
+
+ len = strlen(s) + 1;
+
+ if ((tmp = xmalloc(len)) == NULL)
+ return NULL;
+
+ memcpy(tmp, s, len);
+
+ return tmp;
+}
diff --git a/kstars/kstars/indi/fli/libfli-mem.h b/kstars/kstars/indi/fli/libfli-mem.h
new file mode 100644
index 00000000..c016fc64
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-mem.h
@@ -0,0 +1,54 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_MEM_H_
+#define _LIBFLI_MEM_H_
+
+void *xmalloc(size_t size);
+void *xcalloc(size_t nmemb, size_t size);
+void xfree(void *ptr);
+void *xrealloc(void *ptr, size_t size);
+int xfree_all(void);
+char *xstrdup(const char *s);
+
+#endif /* _LIBFLI_MEM_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-parport.c b/kstars/kstars/indi/fli/libfli-parport.c
new file mode 100644
index 00000000..714e33eb
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-parport.c
@@ -0,0 +1,136 @@
+/*
+
+ 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
+
+*/
+
+#include <sys/ioctl.h>
+#include <asm/param.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "libfli-libfli.h"
+#include "libfli-debug.h"
+#include "libfli-camera.h"
+
+#include "fli_ioctl.h"
+
+long unix_parportio_linux(flidev_t dev, void *buf, long *wlen, long *rlen)
+{
+ fli_unixio_t *io;
+ flicamdata_t *cam;
+ int err = 0, locked = 0;
+ long org_wlen = *wlen, org_rlen = *rlen;
+ int wto, rto, dto;
+ long ticks;
+
+ io = DEVICE->io_data;
+ cam = DEVICE->device_data;
+
+ if ((err = unix_fli_lock(dev)))
+ {
+ debug(FLIDEBUG_WARN, "Lock failed");
+ goto done;
+ }
+
+ locked = 1;
+
+ /* Convert timeout to jiffies */
+#ifdef HZ
+ ticks = HZ;
+#else
+ ticks = sysconf(_SC_CLK_TCK);
+#endif
+ wto = cam->writeto / 1000 * ticks;
+ rto = cam->readto / 1000 * ticks;
+ dto = cam->dirto / 1000 * ticks;
+
+ if (ioctl(io->fd, FLI_SET_WTO, &wto))
+ {
+ err = -errno;
+ goto done;
+ }
+
+ if (ioctl(io->fd, FLI_SET_DTO, &dto))
+ {
+ err = -errno;
+ goto done;
+ }
+
+ if (ioctl(io->fd, FLI_SET_RTO, &rto))
+ {
+ err = -errno;
+ goto done;
+ }
+
+ if ((*wlen = write(io->fd, buf, *wlen)) != org_wlen)
+ {
+ debug(FLIDEBUG_WARN, "write failed, only %d of %d bytes written",
+ *wlen, org_wlen);
+ err = -errno;
+ goto done;
+ }
+
+ if (*rlen > 0)
+ {
+ if ((*rlen = read(io->fd, buf, *rlen)) != org_rlen)
+ {
+ debug(FLIDEBUG_WARN, "read failed, only %d of %d bytes read",
+ *rlen, org_rlen);
+ err = -errno;
+ goto done;
+ }
+ }
+
+ done:
+
+ if (locked)
+ {
+ int r;
+
+ if ((r = unix_fli_unlock(dev)))
+ debug(FLIDEBUG_WARN, "Unlock failed");
+ if (err == 0)
+ err = r;
+ }
+
+ return err;
+}
diff --git a/kstars/kstars/indi/fli/libfli-parport.h b/kstars/kstars/indi/fli/libfli-parport.h
new file mode 100644
index 00000000..ab70c7a7
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-parport.h
@@ -0,0 +1,64 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_PARPORT_H_
+#define _LIBFLI_PARPORT_H_
+
+#if defined(__linux__)
+
+#define unix_parportio unix_parportio_linux
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
+
+#define unix_parportio NULL
+
+#else
+
+#define unix_parportio NULL
+#warning "Unknown system"
+
+#endif
+
+long unix_parportio_linux(flidev_t dev, void *buf, long *wlen, long *rlen);
+
+#endif /* _LIBFLI_PARPORT_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-serial.c b/kstars/kstars/indi/fli/libfli-serial.c
new file mode 100644
index 00000000..5b01e294
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-serial.c
@@ -0,0 +1,189 @@
+/*
+
+ 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
+
+*/
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <termios.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libfli-libfli.h"
+#include "libfli-debug.h"
+#include "libfli-sys.h"
+#include "libfli-serial.h"
+
+long unix_serialio(flidev_t dev, void *buf, long *wlen, long *rlen)
+{
+ int err = 0, locked = 0, gotattr = 0;
+ long org_wlen = *wlen, org_rlen = *rlen;
+ struct termios old_termios, new_termios;
+ fli_unixio_t *io;
+
+ io = DEVICE->io_data;
+
+ if ((err = unix_fli_lock(dev)))
+ {
+ debug(FLIDEBUG_WARN, "Lock failed");
+ goto done;
+ }
+ locked = 1;
+
+ if (tcgetattr(io->fd, &old_termios))
+ {
+ err = -errno;
+ debug(FLIDEBUG_WARN, "tcgetattr() failed: %s", strerror(errno));
+ goto done;
+ }
+ gotattr = 1;
+
+ bzero(&new_termios, sizeof(struct termios));
+ new_termios.c_cflag = CS8 | CREAD | CLOCAL;
+ new_termios.c_cc[VMIN] = 1;
+ new_termios.c_cc[VTIME] = 0;
+
+ /* Set the input baud rate */
+ if (cfsetispeed(&new_termios, BAUDRATE))
+ {
+ err = -errno;
+ debug(FLIDEBUG_WARN, "cfsetispeed() failed: %s", strerror(errno));
+ goto done;
+ }
+ /* Set the output baud rate */
+ if (cfsetospeed(&new_termios, BAUDRATE))
+ {
+ err = -errno;
+ debug(FLIDEBUG_WARN, "cfsetospeed() failed: %s", strerror(errno));
+ goto done;
+ }
+
+ if (tcsetattr(io->fd, TCSANOW, &new_termios))
+ {
+ err = -errno;
+ /* FIX: Should this be FLIDEBUG_FAIL*/
+ debug(FLIDEBUG_WARN, "tcsetattr() failed: %s", strerror(errno));
+ goto done;
+ }
+
+ if ((*wlen = write(io->fd, buf, org_wlen)) != org_wlen)
+ {
+ err = -errno;
+ debug(FLIDEBUG_WARN, "write() failed, only %d of %d bytes written",
+ *wlen, org_wlen);
+ goto done;
+ }
+
+ if (tcdrain(io->fd))
+ {
+ err = -errno;
+ debug(FLIDEBUG_WARN, "tcdrain() failed: %s", strerror(errno));
+ goto done;
+ }
+
+ for (*rlen = 0; *rlen < org_rlen; )
+ {
+ ssize_t r;
+ fd_set readfds;
+ struct timeval timeout;
+
+ timeout.tv_sec = DEVICE->io_timeout / 1000;
+ timeout.tv_usec = (DEVICE->io_timeout % 1000) * 1000;
+
+ FD_ZERO(&readfds);
+ FD_SET(io->fd, &readfds);
+
+ switch (select(io->fd + 1, &readfds, NULL, NULL, &timeout))
+ {
+ case -1: /* An error occurred */
+ err = -errno;
+ debug(FLIDEBUG_WARN, "select() failed: %s", strerror(errno));
+ break;
+
+ case 0: /* A timeout occurred */
+ err = -ETIMEDOUT;
+ debug(FLIDEBUG_WARN, "A serial communication timeout occurred");
+ break;
+
+ default: /* There's some data to read */
+ if ((r = read(io->fd, buf + *rlen, org_rlen - *rlen)) <= 0)
+ {
+ err = -errno;
+ debug(FLIDEBUG_WARN, "read() failed, only %d of %d bytes read",
+ r, org_rlen - *rlen);
+ }
+ else
+ *rlen += r;
+ break;
+ }
+
+ if (err)
+ break;
+ }
+
+ done:
+
+ if (gotattr)
+ {
+ if (tcsetattr(io->fd, TCSANOW, &old_termios))
+ {
+ if (err == 0)
+ err = -errno;
+ debug(FLIDEBUG_WARN,
+ "tcsetattr() failed, could not restore terminal settings: %s",
+ strerror(errno));
+ }
+ }
+
+ if (locked)
+ {
+ int r;
+
+ if ((r = unix_fli_unlock(dev)))
+ debug(FLIDEBUG_WARN, "Unlock failed");
+ if (err == 0)
+ err = r;
+ }
+
+ return err;
+}
diff --git a/kstars/kstars/indi/fli/libfli-serial.h b/kstars/kstars/indi/fli/libfli-serial.h
new file mode 100644
index 00000000..d2456a56
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-serial.h
@@ -0,0 +1,51 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_SERIAL_H_
+#define _LIBFLI_SERIAL_H_
+
+#define BAUDRATE B1200
+
+long unix_serialio(flidev_t dev, void *buf, long *wlen, long *rlen);
+
+#endif /* _LIBFLI_SERIAL_H_ */
diff --git a/kstars/kstars/indi/fli/libfli-sys.c b/kstars/kstars/indi/fli/libfli-sys.c
new file mode 100644
index 00000000..dda7462f
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-sys.c
@@ -0,0 +1,481 @@
+/*
+
+ 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
+
+*/
+
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <glob.h>
+
+#include "libfli-libfli.h"
+#include "libfli-debug.h"
+#include "libfli-mem.h"
+#include "libfli-camera.h"
+#include "libfli-filter-focuser.h"
+#include "libfli-sys.h"
+#include "libfli-parport.h"
+#include "libfli-usb.h"
+#include "libfli-serial.h"
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+static long unix_fli_list_parport(flidomain_t domain, char ***names);
+static long unix_fli_list_usb(flidomain_t domain, char ***names);
+static long unix_fli_list_serial(flidomain_t domain, char ***names);
+
+#ifdef __linux__
+long linux_usb_reset(flidev_t dev);
+#endif
+
+long unix_fli_connect(flidev_t dev, char *name, long domain)
+{
+ fli_unixio_t *io;
+
+ CHKDEVICE(dev);
+
+ if (name == NULL)
+ return -EINVAL;
+
+ /* Lock functions should be set before any other functions used */
+ DEVICE->fli_lock = unix_fli_lock;
+ DEVICE->fli_unlock = unix_fli_unlock;
+
+ DEVICE->domain = domain & 0x00ff;
+ DEVICE->devinfo.type = domain & 0xff00;
+
+ debug(FLIDEBUG_INFO, "Domain: 0x%04x", DEVICE->domain);
+ debug(FLIDEBUG_INFO, " Type: 0x%04x", DEVICE->devinfo.type);
+
+ if ((io = xcalloc(1, sizeof(fli_unixio_t))) == NULL)
+ return -ENOMEM;
+
+ if ((io->fd = open(name, O_RDWR)) == -1)
+ {
+ xfree(io);
+ return -errno;
+ }
+
+ switch (DEVICE->domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ DEVICE->fli_io = unix_parportio;
+ break;
+
+ case FLIDOMAIN_USB:
+ {
+ int r;
+
+ if( (r = unix_usbverifydescriptor(dev, io)) != 0)
+ {
+ close(io->fd);
+ xfree(io);
+ return r;
+ }
+ DEVICE->fli_io = unix_usbio;
+ }
+ break;
+
+ case FLIDOMAIN_SERIAL:
+ DEVICE->fli_io = unix_serialio;
+ break;
+
+ default:
+ close(io->fd);
+ xfree(io);
+ return -EINVAL;
+ }
+
+ switch (DEVICE->devinfo.type)
+ {
+ case FLIDEVICE_CAMERA:
+ DEVICE->fli_open = fli_camera_open;
+ DEVICE->fli_close = fli_camera_close;
+ DEVICE->fli_command = fli_camera_command;
+ break;
+
+ case FLIDEVICE_FOCUSER:
+ DEVICE->fli_open = fli_focuser_open;
+ DEVICE->fli_close = fli_focuser_close;
+ DEVICE->fli_command = fli_focuser_command;
+ break;
+
+ case FLIDEVICE_FILTERWHEEL:
+ DEVICE->fli_open = fli_filter_open;
+ DEVICE->fli_close = fli_filter_close;
+ DEVICE->fli_command = fli_filter_command;
+ break;
+
+ default:
+ close(io->fd);
+ xfree(io);
+ return -EINVAL;
+ }
+
+ DEVICE->io_data = io;
+ DEVICE->name = xstrdup(name);
+ DEVICE->io_timeout = 60 * 1000; /* 1 min. */
+
+ return 0;
+}
+
+long unix_fli_disconnect(flidev_t dev)
+{
+ int err = 0;
+ fli_unixio_t *io;
+
+ CHKDEVICE(dev);
+
+#ifdef __linux__
+ if ((DEVICE->domain & 0x00ff) == FLIDOMAIN_USB) {
+ debug(FLIDEBUG_INFO, "Resetting device");
+ linux_usb_reset(dev);
+ }
+#endif
+
+ if ((io = DEVICE->io_data) == NULL)
+ return -EINVAL;
+
+ if (close(io->fd))
+ err = -errno;
+
+ xfree(DEVICE->io_data);
+
+ DEVICE->io_data = NULL;
+ DEVICE->fli_lock = NULL;
+ DEVICE->fli_unlock = NULL;
+ DEVICE->fli_io = NULL;
+ DEVICE->fli_open = NULL;
+ DEVICE->fli_close = NULL;
+ DEVICE->fli_command = NULL;
+
+ return err;
+}
+
+#if defined(_USE_FLOCK_)
+
+long unix_fli_lock(flidev_t dev)
+{
+ fli_unixio_t *io = DEVICE->io_data;
+
+ if (io == NULL)
+ return -ENODEV;
+
+ if (flock(io->fd, LOCK_EX) == -1)
+ return -errno;
+ else
+ return 0;
+}
+
+long unix_fli_unlock(flidev_t dev)
+{
+ fli_unixio_t *io = DEVICE->io_data;
+
+ if (io == NULL)
+ return -ENODEV;
+
+ if (flock(io->fd, LOCK_UN) == -1)
+ return -errno;
+ else
+ return 0;
+}
+
+#else /* !defined(_USE_FLOCK_) */
+
+#define PUBLIC_DIR "/var/spool/uucppublic"
+
+long unix_fli_lock(flidev_t dev)
+{
+ int fd, err = 0, locked = 0, i;
+ char tmpf[] = PUBLIC_DIR "/temp.XXXXXX", lockf[PATH_MAX], name[PATH_MAX];
+ FILE *f;
+ unsigned int backoff = 10000;
+ pid_t pid;
+
+ if ((fd = mkstemp(tmpf)) == -1)
+ return -errno;
+
+ if ((f = fdopen(fd, "w")) == NULL)
+ {
+ err = -errno;
+ goto done;
+ }
+
+ fprintf(f, "%d\n", getpid());
+ fclose(f);
+
+ if (chmod(tmpf, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
+ S_IROTH | S_IWOTH) == -1)
+ {
+ err = -errno;
+ goto done;
+ }
+
+ for (i = 0; DEVICE->name[i] != '\0' && i < PATH_MAX; i++)
+ name[i] = (DEVICE->name[i] == '/') ? '-' : DEVICE->name[i];
+
+ name[MIN(i, PATH_MAX - 1)] = '\0';
+
+ if (snprintf(lockf, PATH_MAX, PUBLIC_DIR "/libfli%s.lock",
+ name) >= PATH_MAX)
+ {
+ err = -EOVERFLOW;
+ goto done;
+ }
+
+ do {
+ if (link(tmpf, lockf) == -1)
+ {
+ int r;
+
+ if (errno != EEXIST)
+ {
+ err = -errno;
+ goto done;
+ }
+
+ if ((f = fopen(lockf, "r")) == NULL)
+ continue;
+
+ r = fscanf(f, "%d\n", &pid);
+ fclose(f);
+ if (r != 1)
+ continue;
+
+ if (kill(pid, 0))
+ {
+ if (errno == ESRCH)
+ {
+ debug(FLIDEBUG_WARN, "Removing stale lock file");
+ unlink(lockf);
+ }
+
+ continue;
+ }
+ else
+ {
+ usleep(backoff);
+ if ((backoff <<= 2) == 0)
+ {
+ err = -ETIMEDOUT;
+ goto done;
+ }
+ }
+ }
+ else
+ locked = 1;
+ } while (!locked);
+
+ done:
+
+ unlink(tmpf);
+
+ return err;
+}
+
+long unix_fli_unlock(flidev_t dev)
+{
+ char lockf[PATH_MAX], name[PATH_MAX];
+ FILE *f;
+ pid_t pid = -1;
+ int i;
+
+ for (i = 0; DEVICE->name[i] != '\0' && i < PATH_MAX; i++)
+ name[i] = (DEVICE->name[i] == '/') ? '-' : DEVICE->name[i];
+
+ name[MIN(i, PATH_MAX - 1)] = '\0';
+
+ if (snprintf(lockf, PATH_MAX, PUBLIC_DIR "/libfli%s.lock",
+ name) >= PATH_MAX)
+ return -EOVERFLOW;
+
+ if ((f = fopen(lockf, "r")) == NULL)
+ {
+ debug(FLIDEBUG_WARN, "Trying to unlock `%s' when not locked",
+ DEVICE->name);
+ return -errno;
+ }
+
+ if (fscanf(f, "%d\n", &pid) != 1)
+ debug(FLIDEBUG_WARN, "Invalid lock file for `%s'", DEVICE->name);
+
+ fclose(f);
+
+ if (pid != -1 && pid != getpid())
+ debug(FLIDEBUG_WARN, "Forcing unlock of `%s' from process %d",
+ DEVICE->name, pid);
+
+ unlink(lockf);
+
+ return 0;
+}
+
+#undef PUBLIC_DIR
+
+#endif /* defined(_USE_FLOCK_) */
+
+long unix_fli_list(flidomain_t domain, char ***names)
+{
+ *names = NULL;
+
+ switch (domain & 0x00ff)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ return unix_fli_list_parport(domain, names);
+ break;
+
+ case FLIDOMAIN_USB:
+ return unix_fli_list_usb(domain, names);
+ break;
+
+ case FLIDOMAIN_SERIAL:
+ return unix_fli_list_serial(domain, names);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* Not reached */
+ return -EINVAL;
+}
+
+static long unix_fli_list_glob(char *pattern, flidomain_t domain,
+ char ***names)
+{
+ int retval, i, found = 0;
+ char **list;
+ glob_t g;
+
+ if ((retval = glob(pattern, 0, NULL, &g)))
+ {
+#ifdef GLOB_NOMATCH
+ if (retval != GLOB_NOMATCH)
+ {
+ globfree(&g);
+ return -errno;
+ }
+
+ /* retval == GLOB_NOMATCH */
+ g.gl_pathc = 0;
+#else
+ globfree(&g);
+ return -errno;
+#endif
+ }
+
+ if ((list = xmalloc((g.gl_pathc + 1) * sizeof(char *))) == NULL)
+ {
+ globfree(&g);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < (int) g.gl_pathc; i++)
+ {
+ flidev_t dev;
+
+ if (FLIOpen(&dev, g.gl_pathv[i], domain))
+ continue;
+
+ if ((list[found] = xmalloc(strlen(g.gl_pathv[i]) +
+ strlen(DEVICE->devinfo.model) + 2)) == NULL)
+ {
+ int j;
+
+ FLIClose(dev);
+ for (j = 0; j < found; j++)
+ xfree(list[j]);
+ xfree(list);
+ globfree(&g);
+ return -ENOMEM;
+ }
+
+ sprintf(list[found], "%s;%s", g.gl_pathv[i], DEVICE->devinfo.model);
+ FLIClose(dev);
+ found++;
+ }
+
+ globfree(&g);
+
+ /* Terminate the list */
+ list[found++] = NULL;
+
+ list = xrealloc(list, found * sizeof(char *));
+ *names = list;
+
+ return 0;
+}
+
+#ifdef __linux__
+
+static long unix_fli_list_parport(flidomain_t domain, char ***names)
+{
+ return unix_fli_list_glob(PARPORT_GLOB, domain, names);
+}
+
+#else
+
+static long unix_fli_list_parport(flidomain_t domain, char ***names)
+{
+ return -EINVAL;
+}
+
+#endif
+
+static long unix_fli_list_usb(flidomain_t domain, char ***names)
+{
+ return unix_fli_list_glob(USB_GLOB, domain, names);
+}
+
+static long unix_fli_list_serial(flidomain_t domain, char ***names)
+{
+ return unix_fli_list_glob(SERIAL_GLOB, domain, names);
+}
diff --git a/kstars/kstars/indi/fli/libfli-sys.h b/kstars/kstars/indi/fli/libfli-sys.h
new file mode 100644
index 00000000..a5d94bd5
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-sys.h
@@ -0,0 +1,108 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_SYS_H
+#define _LIBFLI_SYS_H
+
+#include <limits.h>
+
+#define LIBFLIAPI long
+
+#if defined(__linux__)
+
+#define __SYSNAME__ "Linux"
+#define __LIBFLI_MINOR__ 11
+#define USB_READ_SIZ_MAX 4096 /* Can only read a page at a time */
+#define _USE_FLOCK_
+#define PARPORT_GLOB "/dev/ccd*"
+#define USB_GLOB "/proc/bus/usb/*/*"
+#define SERIAL_GLOB "/dev/ttyS[0-9]*"
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+// FIXME - this does not actually work on OSX
+
+#define __SYSNAME__ "FreeBSD"
+#define __LIBFLI_MINOR__ 1
+#define USB_READ_SIZ_MAX (1024 *1024) /* 1 MB (This is arbitrary, but
+ * must be able to malloc this amount.)
+ */
+#define USB_GLOB "/dev/ugen*." __STRINGIFY(FLI_CMD_ENDPOINT)
+#define SERIAL_GLOB "/dev/cuaa*"
+
+#elif defined (__NetBSD__)
+
+#define __SYSNAME__ "NetBSD"
+#define __LIBFLI_MINOR__ 1
+#define USB_READ_SIZ_MAX (1024 *1024) /* 1 MB (This is arbitrary, but
+ * must be able to malloc this amount.)
+ */
+#define USB_GLOB "/dev/ugen*.0" __STRINGIFY(FLI_CMD_ENDPOINT)
+#define SERIAL_GLOB "/dev/dty0*"
+
+#else
+
+#define __SYSNAME__ "Unknown"
+#define __LIBFLI_MINOR__ 1
+#define USB_READ_SIZ_MAX 0
+#define USB_GLOB ""
+#define SERIAL_GLOB ""
+
+#warning "Unknown system"
+
+#endif
+
+typedef struct {
+ int fd;
+} fli_unixio_t;
+
+long unix_fli_connect(flidev_t dev, char *name, long domain);
+long unix_fli_disconnect(flidev_t dev);
+long unix_fli_lock(flidev_t dev);
+long unix_fli_unlock(flidev_t dev);
+long unix_fli_list(flidomain_t domain, char ***names);
+
+#define fli_connect unix_fli_connect
+#define fli_disconnect unix_fli_disconnect
+#define fli_list unix_fli_list
+
+#endif /* _LIBFLI_SYS_H */
diff --git a/kstars/kstars/indi/fli/libfli-usb-sys-bsd.c b/kstars/kstars/indi/fli/libfli-usb-sys-bsd.c
new file mode 100644
index 00000000..d1f6a2b0
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-usb-sys-bsd.c
@@ -0,0 +1,133 @@
+/*
+
+ 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
+
+*/
+
+#include <sys/types.h>
+#include <dev/usb/usb.h>
+#include <sys/ioctl.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "libfli-libfli.h"
+#include "libfli-sys.h"
+#include "libfli-usb.h"
+
+long unix_usbverifydescriptor(flidev_t dev, fli_unixio_t *io)
+{
+ usb_device_descriptor_t usb_desc;
+ int r;
+
+ if ((r = read(io->fd, &usb_desc, sizeof(usb_device_descriptor_t))) !=
+ sizeof(usb_device_descriptor_t))
+ {
+ debug(FLIDEBUG_FAIL, "linux_usbverifydescriptor(): Could not read descriptor.");
+ return -EIO;
+ }
+ else
+ {
+ debug(FLIDEBUG_INFO, "USB device descriptor:");
+ if(usb_desc.idVendor != 0x0f18)
+ {
+ debug(FLIDEBUG_FAIL, "linux_usbverifydescriptor(): Not a FLI device!");
+ return -ENODEV;
+ }
+
+ switch(DEVICE->domain)
+ {
+ case FLIDOMAIN_USB:
+ if(usb_desc.idProduct != 0x0002)
+ {
+ return -ENODEV;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ DEVICE->devinfo.fwrev = usb_desc.bcdDevice;
+ }
+
+ return 0;
+}
+
+long bsd_bulkwrite(flidev_t dev, void *buf, long *wlen)
+{
+ fli_unixio_t *io;
+ long org_wlen = *wlen;
+ int to;
+
+ io = DEVICE->io_data;
+ to = DEVICE->io_timeout;
+
+ if (ioctl(io->fd, USB_SET_TIMEOUT, &to) == -1)
+ return -errno;
+
+ *wlen = write(io->fd, buf, *wlen);
+
+ if (*wlen != org_wlen)
+ return -errno;
+ else
+ return 0;
+}
+
+long bsd_bulkread(flidev_t dev, void *buf, long *rlen)
+{
+ fli_unixio_t *io;
+ long org_rlen = *rlen;
+ int to;
+
+ io = DEVICE->io_data;
+ to = DEVICE->io_timeout;
+
+ if (ioctl(io->fd, USB_SET_TIMEOUT, &to) == -1)
+ return -errno;
+
+ *rlen = read(io->fd, buf, *rlen);
+
+ if (*rlen != org_rlen)
+ return -errno;
+ else
+ return 0;
+}
diff --git a/kstars/kstars/indi/fli/libfli-usb-sys-linux.c b/kstars/kstars/indi/fli/libfli-usb-sys-linux.c
new file mode 100644
index 00000000..d35858a4
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-usb-sys-linux.c
@@ -0,0 +1,225 @@
+/*
+
+ 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
+
+*/
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+
+#include <errno.h>
+
+#include "libfli-libfli.h"
+#include "libfli-sys.h"
+#include "libfli-usb.h"
+
+#define USB_DIR_OUT 0 /* to device */
+#define USB_DIR_IN 0x80 /* to host */
+#define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int)
+#define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer)
+#define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int)
+#define IOCTL_USB_RESET _IO('U', 20)
+
+/* Device descriptor */
+typedef struct
+{
+ u_int8_t bLength;
+ u_int8_t bDescriptorType;
+ u_int16_t bcdUSB;
+ u_int8_t bDeviceClass;
+ u_int8_t bDeviceSubClass;
+ u_int8_t bDeviceProtocol;
+ u_int8_t bMaxPacketSize0;
+ u_int16_t idVendor;
+ u_int16_t idProduct;
+ u_int16_t bcdDevice;
+ u_int8_t iManufacturer;
+ u_int8_t iProduct;
+ u_int8_t iSerialNumber;
+ u_int8_t bNumConfigurations;
+} usb_device_descriptor __attribute__ ((packed));
+
+struct usbdevfs_bulktransfer {
+ unsigned int ep;
+ unsigned int len;
+ unsigned int timeout; /* in milliseconds */
+ void *data;
+};
+
+long linux_usb_reset(flidev_t dev);
+
+long unix_usbverifydescriptor(flidev_t dev, fli_unixio_t *io)
+{
+ usb_device_descriptor usb_desc;
+ int r;
+
+ if ((r = read(io->fd, &usb_desc, sizeof(usb_device_descriptor))) !=
+ sizeof(usb_device_descriptor))
+ {
+ debug(FLIDEBUG_FAIL, "linux_usbverifydescriptor(): Could not read descriptor.");
+ return -EIO;
+ }
+ else
+ {
+ debug(FLIDEBUG_INFO, "USB device descriptor:");
+ if(usb_desc.idVendor != 0x0f18)
+ {
+ debug(FLIDEBUG_FAIL, "linux_usbverifydescriptor(): Not a FLI device!");
+ return -ENODEV;
+ }
+
+ switch(DEVICE->domain)
+ {
+ case FLIDOMAIN_USB:
+ if( (usb_desc.idProduct != 0x0002) &&
+ (usb_desc.idProduct != 0x0006) &&
+ (usb_desc.idProduct != 0x0007) ) {
+ return -ENODEV;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ DEVICE->devinfo.fwrev = usb_desc.bcdDevice;
+ }
+
+ return 0;
+}
+
+static long linux_bulktransfer(flidev_t dev, int ep, void *buf, long *len)
+{
+ fli_unixio_t *io;
+ unsigned int iface = 0;
+ struct usbdevfs_bulktransfer bulk;
+ unsigned int tbytes = 0;
+ long bytes;
+
+/* This section of code has been modified since the Linux kernel has (had)
+ a 4096 byte limit (kernel page size) on the IOCTL for data transfer.
+ We ran into a problem when the CCD camera became large and the data
+ transfer requirements grew. */
+
+ io = DEVICE->io_data;
+
+ /* Claim the interface */
+ if (ioctl(io->fd, USBDEVFS_CLAIMINTERFACE, &iface))
+ return -errno;
+
+/* #define _DEBUG */
+
+#ifdef _DEBUG
+
+ if ((ep & 0xf0) == 0) {
+ char buffer[1024];
+ int i;
+
+ sprintf(buffer, "OUT %6ld: ", *len);
+ for (i = 0; i < ((*len > 16)?16:*len); i++) {
+ sprintf(buffer + strlen(buffer), "%02x ", ((unsigned char *) buf)[i]);
+ }
+
+ debug(FLIDEBUG_INFO, buffer);
+ }
+
+#endif /* _DEBUG */
+
+ while (tbytes < (unsigned) *len) {
+ bulk.ep = ep;
+ bulk.len = ((*len - tbytes) > 4096)?4096:(*len - tbytes);
+ bulk.timeout = DEVICE->io_timeout;
+ bulk.data = buf + tbytes;
+
+ /* This ioctl return the number of bytes transfered */
+ if((bytes = ioctl(io->fd, USBDEVFS_BULK, &bulk)) != (long) bulk.len)
+ break;
+
+ tbytes += bytes;
+ }
+
+#ifdef _DEBUG
+
+ if ((ep & 0xf0) != 0) {
+ char buffer[1024];
+ int i;
+
+ sprintf(buffer, " IN %6ld: ", *len);
+ for (i = 0; i < ((*len > 16)?16:*len); i++) {
+ sprintf(buffer + strlen(buffer), "%02x ", ((unsigned char *) buf)[i]);
+ }
+
+ debug(FLIDEBUG_INFO, buffer);
+ }
+
+#endif /* _DEBUG */
+
+ /* Release the interface */
+/* if (ioctl(io->fd, USBDEVFS_RELEASEINTERFACE, &iface))
+ return -errno; */
+
+ if ((unsigned) *len != tbytes)
+ return -errno;
+ else
+ return 0;
+}
+
+long linux_bulkwrite(flidev_t dev, void *buf, long *wlen)
+{
+ return linux_bulktransfer(dev, FLI_CMD_ENDPOINT | USB_DIR_OUT, buf, wlen);
+}
+
+long linux_bulkread(flidev_t dev, void *buf, long *rlen)
+{
+ return linux_bulktransfer(dev, FLI_CMD_ENDPOINT | USB_DIR_IN, buf, rlen);
+}
+
+long linux_usb_reset(flidev_t dev)
+{
+ fli_unixio_t *io;
+
+ io = DEVICE->io_data;
+
+ return (ioctl(io->fd, IOCTL_USB_RESET, NULL));
+
+}
diff --git a/kstars/kstars/indi/fli/libfli-usb-sys-null.c b/kstars/kstars/indi/fli/libfli-usb-sys-null.c
new file mode 100644
index 00000000..2b73b202
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-usb-sys-null.c
@@ -0,0 +1,67 @@
+/*
+
+ 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
+
+*/
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "libfli-libfli.h"
+#include "libfli-sys.h"
+#include "libfli-usb.h"
+
+long null_bulkwrite(flidev_t dev, void *buf, long *wlen)
+{
+ return -errno;
+}
+
+long null_bulkread(flidev_t dev, void *buf, long *rlen)
+{
+ return -errno;
+}
+
+long unix_usbverifydescriptor(flidev_t dev, fli_unixio_t *io)
+{
+ return -errno;
+}
diff --git a/kstars/kstars/indi/fli/libfli-usb.c b/kstars/kstars/indi/fli/libfli-usb.c
new file mode 100644
index 00000000..b816d6b2
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-usb.c
@@ -0,0 +1,94 @@
+/*
+
+ 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
+
+*/
+
+#include <errno.h>
+
+#include "libfli-libfli.h"
+#include "libfli-debug.h"
+#include "libfli-sys.h"
+#include "libfli-usb.h"
+
+long unix_usbio(flidev_t dev, void *buf, long *wlen, long *rlen)
+{
+ int err = 0, locked = 0;
+ long org_wlen = *wlen, org_rlen = *rlen;
+
+ if ((err = unix_fli_lock(dev)))
+ {
+ debug(FLIDEBUG_WARN, "Lock failed");
+ goto done;
+ }
+
+ locked = 1;
+
+ if ((err = unix_bulkwrite(dev, buf, wlen)))
+ {
+ debug(FLIDEBUG_WARN, "Bulkwrite failed, only %d of %d bytes written",
+ *wlen, org_wlen);
+ goto done;
+ }
+
+ if (*rlen > 0)
+ {
+ if ((err = unix_bulkread(dev, buf, rlen)))
+ {
+ debug(FLIDEBUG_WARN, "Bulkread failed, only %d of %d bytes read",
+ *rlen, org_rlen);
+ goto done;
+ }
+ }
+
+ done:
+
+ if (locked)
+ {
+ int r;
+
+ if ((r = unix_fli_unlock(dev)))
+ debug(FLIDEBUG_WARN, "Unlock failed");
+ if (err == 0)
+ err = r;
+ }
+
+ return err;
+}
diff --git a/kstars/kstars/indi/fli/libfli-usb.h b/kstars/kstars/indi/fli/libfli-usb.h
new file mode 100644
index 00000000..f982b4f8
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli-usb.h
@@ -0,0 +1,69 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_USB_H_
+#define _LIBFLI_USB_H_
+
+#define FLI_CMD_ENDPOINT 2
+
+#if defined(__linux__)
+#define unix_bulkwrite linux_bulkwrite
+#define unix_bulkread linux_bulkread
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
+#define unix_bulkwrite bsd_bulkwrite
+#define unix_bulkread bsd_bulkread
+
+#else
+#define unix_bulkwrite null_bulkwrite
+#define unix_bulkread null_bulkread
+
+#warning "using null I/O operations!"
+#endif
+
+long unix_bulkwrite(flidev_t dev, void *buf, long *wlen);
+long unix_bulkread(flidev_t dev, void *buf, long *rlen);
+long unix_usbio(flidev_t dev, void *buf, long *wlen, long *rlen);
+long unix_usbverifydescriptor(flidev_t dev, fli_unixio_t *io);
+
+#endif /* _LIBFLI_USB_H_ */
diff --git a/kstars/kstars/indi/fli/libfli.c b/kstars/kstars/indi/fli/libfli.c
new file mode 100644
index 00000000..68df7945
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli.c
@@ -0,0 +1,1383 @@
+/*
+
+ Copyright (c) 2000, 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
+
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "libfli-libfli.h"
+#include "libfli-mem.h"
+#include "libfli-debug.h"
+
+static long devalloc(flidev_t *dev);
+static long devfree(flidev_t dev);
+static long fli_open(flidev_t *dev, char *name, long domain);
+static long fli_close(flidev_t dev);
+static long fli_freelist(char **names);
+
+flidevdesc_t *devices[MAX_OPEN_DEVICES] = {NULL,};
+
+const char* version =
+"FLI Software Development Library for " __SYSNAME__ " " __LIBFLIVER__;
+
+static long devalloc(flidev_t *dev)
+{
+ int i;
+
+ if (dev == NULL)
+ return -EINVAL;
+
+ for (i = 0; i < MAX_OPEN_DEVICES; i++)
+ if (devices[i] == NULL)
+ break;
+
+ if (i == MAX_OPEN_DEVICES)
+ return -ENODEV;
+
+ if ((devices[i] =
+ (flidevdesc_t *)xcalloc(1, sizeof(flidevdesc_t))) == NULL)
+ return -ENOMEM;
+
+ *dev = i;
+
+ return 0;
+}
+
+static long devfree(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ if (DEVICE->io_data != NULL)
+ {
+ debug(FLIDEBUG_WARN, "close didn't free io_data (not NULL)");
+ xfree(DEVICE->io_data);
+ DEVICE->io_data = NULL;
+ }
+ if (DEVICE->device_data != NULL)
+ {
+ debug(FLIDEBUG_WARN, "close didn't free device_data (not NULL)");
+ xfree(DEVICE->device_data);
+ DEVICE->device_data = NULL;
+ }
+ if (DEVICE->sys_data != NULL)
+ {
+ debug(FLIDEBUG_WARN, "close didn't free sys_data (not NULL)");
+ xfree(DEVICE->sys_data);
+ DEVICE->sys_data = NULL;
+ }
+
+ if (DEVICE->name != NULL)
+ {
+ xfree(DEVICE->name);
+ DEVICE->name = NULL;
+ }
+
+ xfree(DEVICE);
+ DEVICE = NULL;
+
+ return 0;
+}
+
+static long fli_open(flidev_t *dev, char *name, long domain)
+{
+ int retval;
+
+ debug(FLIDEBUG_INFO, "Entering FLIOpen()");
+ debug(FLIDEBUG_INFO, "Trying to open file <%s> in domain %d.",
+ name, domain);
+
+ if ((retval = devalloc(dev)) != 0)
+ {
+ debug(FLIDEBUG_WARN, "error devalloc() %d [%s]",
+ retval, strerror(-retval));
+ return retval;
+ }
+
+ debug(FLIDEBUG_INFO, "Got device index %d", *dev);
+
+ if ((retval = fli_connect(*dev, name, domain)) != 0)
+ {
+ debug(FLIDEBUG_WARN, "fli_connect() error %d [%s]",
+ retval, strerror(-retval));
+ devfree(*dev);
+ return retval;
+ }
+
+ if ((retval = devices[*dev]->fli_open(*dev)) != 0)
+ {
+ debug(FLIDEBUG_WARN, "fli_open() error %d [%s]",
+ retval, strerror(-retval));
+ fli_disconnect(*dev);
+ devfree(*dev);
+ return retval;
+ }
+
+ return retval;
+}
+
+static long fli_close(flidev_t dev)
+{
+ CHKDEVICE(dev);
+ CHKFUNCTION(DEVICE->fli_close);
+
+ DEVICE->fli_close(dev);
+ fli_disconnect(dev);
+ devfree(dev);
+
+ return 0;
+}
+
+static long fli_freelist(char **names)
+{
+ int i;
+
+ if (names == NULL)
+ return 0;
+
+ for (i = 0; names[i] != NULL; i++)
+ xfree(names[i]);
+ xfree(names);
+
+ return 0;
+}
+
+LIBFLIAPI FLIGrabFrame(flidev_t dev, void* buff,
+ size_t buffsize, size_t* bytesgrabbed)
+{
+ dev=dev; buff=buff; buffsize=buffsize;bytesgrabbed=bytesgrabbed;
+ return -EFAULT;
+}
+
+/**
+ Get a handle to an FLI device. This function requires the filename
+ and domain of the requested device. Valid device filenames can be
+ obtained using the \texttt{FLIList()} function. An application may
+ use any number of handles associated with the same physical
+ device. When doing so, it is important to lock the appropriate
+ device to ensure that multiple accesses to the same device do not
+ occur during critical operations.
+
+ @param dev Pointer to where a device handle will be placed.
+
+ @param name Pointer to a string where the device filename to be
+ opened is stored. For parallel port devices that are not probed by
+ \texttt{FLIList()} (Windows 95/98/Me), place the address of the
+ parallel port in a string in ascii form ie: "0x378".
+
+ @param domain Domain to apply to \texttt{name} for device opening.
+ This is a bitwise ORed combination of interface method and device
+ type. Valid interfaces include \texttt{FLIDOMAIN_PARALLEL_PORT},
+ \texttt{FLIDOMAIN_USB}, \texttt{FLIDOMAIN_SERIAL}, and
+ \texttt{FLIDOMAIN_INET}. Valid device types include
+ \texttt{FLIDEVICE_CAMERA}, \texttt{FLIDOMAIN_FILTERWHEEL}, and
+ \texttt{FLIDOMAIN_FOCUSER}.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIList
+ @see FLIClose
+ @see flidomain_t
+*/
+LIBFLIAPI FLIOpen(flidev_t *dev, char *name, flidomain_t domain)
+{
+ return fli_open(dev, name, domain);
+}
+
+/**
+ Enable debugging of API operations and communications. Use this
+ function in combination with FLIDebug to assist in diagnosing
+ problems that may be encountered during programming.
+
+ @param host Name of the file to send debugging information to.
+ This parameter is ignored under Linux where \texttt{syslog(3)} is
+ used to send debug messages (see \texttt{syslog.conf(5)} for how to
+ configure syslogd).
+
+ @param level Debug level. A value of \texttt{FLIDEBUG_NONE} disables
+ debugging. Values of \texttt{FLIDEBUG_FAIL}, \texttt{FLIDEBUG_WARN}, and
+ \texttt{FLIDEBUG_INFO} enable progressively more verbose debug messages.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+*/
+LIBFLIAPI FLISetDebugLevel(char *host, flidebug_t level)
+{
+ setdebuglevel(host, level);
+ return 0;
+}
+
+/**
+ Close a handle to a FLI device.
+
+ @param dev The device handle to be closed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIOpen
+*/
+LIBFLIAPI FLIClose(flidev_t dev)
+{
+ return fli_close(dev);
+}
+
+/**
+ Get the current library version. This function copies up to
+ \texttt{len - 1} characters of the current library version string
+ followed by a terminating \texttt{NULL} character into the buffer
+ pointed to by \texttt{ver}.
+
+ @param ver Pointer to a character buffer where the library version
+ string is to be placed.
+
+ @param len The size in bytes of the buffer pointed to by
+ \texttt{ver}.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+*/
+LIBFLIAPI FLIGetLibVersion(char* ver, size_t len)
+{
+ if (len > 0 && ver == NULL)
+ return -EINVAL;
+
+ if ((size_t) snprintf(ver, len, "%s", version) >= len)
+ return -EOVERFLOW;
+ else
+ return 0;
+}
+
+/**
+ Get the model of a given device. This function copies up to
+ \texttt{len - 1} characters of the model string for device
+ \texttt{dev}, followed by a terminating \texttt{NULL} character
+ into the buffer pointed to by \texttt{model}.
+
+ @param dev Device to find model of.
+
+ @param model Pointer to a character buffer where the model string
+ is to be placed.
+
+ @param len The size in bytes of buffer pointed to by
+ \texttt{model}.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetHWRevision
+ @see FLIGetFWRevision
+ @see FLIGetSerialNum
+*/
+LIBFLIAPI FLIGetModel(flidev_t dev, char* model, size_t len)
+{
+ if (model == NULL)
+ return -EINVAL;
+
+ CHKDEVICE(dev);
+
+ if (DEVICE->devinfo.model == NULL)
+ {
+ model[0] = '\0';
+ return 0;
+ }
+
+ if ((size_t) snprintf(model, len, "%s", DEVICE->devinfo.model) >= len)
+ return -EOVERFLOW;
+ else
+ return 0;
+}
+
+/**
+ Find the dimensions of a pixel in the array of the given device.
+
+ @param dev Device to find the pixel size of.
+
+ @param pixel_x Pointer to a double which will receive the size (in
+ microns) of a pixel in the x direction.
+
+ @param pixel_y Pointer to a double which will receive the size (in
+ microns) of a pixel in the y direction.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetArrayArea
+ @see FLIGetVisibleArea
+*/
+LIBFLIAPI FLIGetPixelSize(flidev_t dev, double *pixel_x, double *pixel_y)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_PIXEL_SIZE, 2,
+ pixel_x, pixel_y);
+}
+
+/**
+ Get the hardware revision of a given device.
+
+ @param dev Device to find the hardware revision of.
+
+ @param hwrev Pointer to a long which will receive the hardware
+ revision.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetModel
+ @see FLIGetFWRevision
+ @see FLIGetSerialNum
+*/
+LIBFLIAPI FLIGetHWRevision(flidev_t dev, long *hwrev)
+{
+ CHKDEVICE(dev);
+
+ *hwrev = DEVICE->devinfo.hwrev;
+ return 0;
+}
+
+/**
+ Get firmware revision of a given device.
+
+ @param dev Device to find the firmware revision of.
+
+ @param fwrev Pointer to a long which will receive the firmware
+ revision.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetModel
+ @see FLIGetHWRevision
+ @see FLIGetSerialNum
+*/
+LIBFLIAPI FLIGetFWRevision(flidev_t dev, long *fwrev)
+{
+ CHKDEVICE(dev);
+
+ *fwrev = DEVICE->devinfo.fwrev;
+ return 0;
+}
+
+/**
+ Get the array area of the given camera. This function finds the
+ \emph{total} area of the CCD array for camera \texttt{dev}. This
+ area is specified in terms of a upper-left point and a lower-right
+ point. The upper-left x-coordinate is placed in \texttt{ul_x}, the
+ upper-left y-coordinate is placed in \texttt{ul_y}, the lower-right
+ x-coordinate is placed in \texttt{lr_x}, and the lower-right
+ y-coordinate is placed in \texttt{lr_y}.
+
+ @param dev Camera to get the array area of.
+
+ @param ul_x Pointer to where the upper-left x-coordinate is to be
+ placed.
+
+ @param ul_y Pointer to where the upper-left y-coordinate is to be
+ placed.
+
+ @param lr_x Pointer to where the lower-right x-coordinate is to be
+ placed.
+
+ @param lr_y Pointer to where the lower-right y-coordinate is to be
+ placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetVisibleArea
+ @see FLISetImageArea
+*/
+LIBFLIAPI FLIGetArrayArea(flidev_t dev, long* ul_x, long* ul_y,
+ long* lr_x, long* lr_y)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_ARRAY_AREA, 4,
+ ul_x, ul_y, lr_x, lr_y);
+}
+
+/**
+ Get the visible area of the given camera. This function finds the
+ \emph{visible} area of the CCD array for the camera \texttt{dev}.
+ This area is specified in terms of a upper-left point and a
+ lower-right point. The upper-left x-coordinate is placed in
+ \texttt{ul_x}, the upper-left y-coordinate is placed in
+ \texttt{ul_y}, the lower-right x-coordinate is placed in
+ \texttt{lr_x}, the lower-right y-coordinate is placed in
+ \texttt{lr_y}.
+
+ @param dev Camera to get the visible area of.
+
+ @param ul_x Pointer to where the upper-left x-coordinate is to be
+ placed.
+
+ @param ul_y Pointer to where the upper-left y-coordinate is to be
+ placed.
+
+ @param lr_x Pointer to where the lower-right x-coordinate is to be
+ placed.
+
+ @param lr_y Pointer to where the lower-right y-coordinate is to be
+ placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetArrayArea
+ @see FLISetImageArea
+*/
+LIBFLIAPI FLIGetVisibleArea(flidev_t dev, long* ul_x, long* ul_y,
+ long* lr_x, long* lr_y)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_VISIBLE_AREA, 4,
+ ul_x, ul_y, lr_x, lr_y);
+}
+
+/**
+ Set the exposure time for a camera. This function sets the
+ exposure time for the camera \texttt{dev} to \texttt{exptime} msec.
+
+ @param dev Camera to set the exposure time of.
+
+ @param exptime Exposure time in msec.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIExposeFrame
+ @see FLICancelExposure
+ @see FLIGetExposureStatus
+*/
+LIBFLIAPI FLISetExposureTime(flidev_t dev, long exptime)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_EXPOSURE_TIME, 1, &exptime);
+}
+
+/**
+ Set the image area for a given camera. This function sets the
+ image area for camera \texttt{dev} to an area specified in terms of
+ a upper-left point and a lower-right point. The upper-left
+ x-coordinate is \texttt{ul_x}, the upper-left y-coordinate is
+ \texttt{ul_y}, the lower-right x-coordinate is \texttt{lr_x}, and
+ the lower-right y-coordinate is \texttt{lr_y}. Note that the given
+ lower-right coordinate must take into account the horizontal and
+ vertical bin factor settings, but the upper-left coordinate is
+ absolute. In other words, the lower-right coordinate used to set
+ the image area is a virtual point $(lr_x', lr_y')$ determined by:
+
+ \[ lr_x' = ul_x + (lr_x - ul_x) / hbin \]
+ \[ lr_y' = ul_y + (lr_y - ul_y) / vbin \]
+
+ Where $(lr_x', lr_y')$ is the coordinate to pass to the
+ \texttt{FLISetImageArea} function, $(ul_x, ul_y)$ and $(lr_x,
+ lr_y)$ are the absolute coordinates of the desired image area,
+ $hbin$ is the horizontal bin factor, and $vbin$ is the vertical bin
+ factor.
+
+ @param dev Camera to set image area of.
+
+ @param ul_x Upper-left x-coordinate of image area.
+
+ @param ul_y Upper-left y-coordinate of image area.
+
+ @param lr_x Lower-right x-coordinate of image area ($lr_x'$ from
+ above).
+
+ @param lr_y Lower-right y-coordinate of image area ($lr_y'$ from
+ above).
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetVisibleArea
+ @see FLIGetArrayArea
+*/
+LIBFLIAPI FLISetImageArea(flidev_t dev, long ul_x, long ul_y,
+ long lr_x, long lr_y)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_IMAGE_AREA, 4,
+ &ul_x, &ul_y, &lr_x, &lr_y);
+}
+
+/**
+ Set the horizontal bin factor for a given camera. This function
+ sets the horizontal bin factor for the camera \texttt{dev} to
+ \texttt{hbin}. The valid range of the \texttt{hbin} parameter is
+ from 1 to 16.
+
+ @param dev Camera to set horizontal bin factor of.
+
+ @param hbin Horizontal bin factor.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLISetVBin
+ @see FLISetImageArea
+*/
+LIBFLIAPI FLISetHBin(flidev_t dev, long hbin)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_HBIN, 1, &hbin);
+}
+
+/**
+ Set the vertical bin factor for a given camera. This function sets
+ the vertical bin factor for the camera \texttt{dev} to
+ \texttt{vbin}. The valid range of the \texttt{vbin} parameter is
+ from 1 to 16.
+
+ @param dev Camera to set vertical bin factor of.
+
+ @param vbin Vertical bin factor.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLISetHBin
+ @see FLISetImageArea
+*/
+LIBFLIAPI FLISetVBin(flidev_t dev, long vbin)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_VBIN, 1, &vbin);
+}
+
+/**
+ Set the frame type for a given camera. This function sets the frame type
+ for camera \texttt{dev} to \texttt{frametype}. The \texttt{frametype}
+ parameter is either \texttt{FLI_FRAME_TYPE_NORMAL} for a normal frame
+ where the shutter opens or \texttt{FLI_FRAME_TYPE_DARK} for a dark frame
+ where the shutter remains closed.
+
+ @param cam Camera to set the frame type of.
+
+ @param frametype Frame type: \texttt{FLI_FRAME_TYPE_NORMAL} or \texttt{FLI_FRAME_TYPE_DARK}.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see fliframe_t
+ @see FLIExposeFrame
+*/
+LIBFLIAPI FLISetFrameType(flidev_t dev, fliframe_t frametype)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_FRAME_TYPE, 1, &frametype);
+}
+
+/**
+ Cancel an exposure for a given camera. This function cancels an
+ exposure in progress by closing the shutter.
+
+ @param dev Camera to cancel the exposure of.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIExposeFrame
+ @see FLIGetExposureStatus
+ @see FLISetExposureTime
+*/
+LIBFLIAPI FLICancelExposure(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_CANCEL_EXPOSURE, 0);
+}
+
+/**
+ Find the remaining exposure time of a given camera. This functions
+ places the remaining exposure time (in milliseconds) in the
+ location pointed to by \texttt{timeleft}.
+
+ @param dev Camera to find the remaining exposure time of.
+
+ @param timeleft Pointer to where the remaining exposure time (in milliseonds) will be placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIExposeFrame
+ @see FLICancelExposure
+ @see FLISetExposureTime
+*/
+LIBFLIAPI FLIGetExposureStatus(flidev_t dev, long *timeleft)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_EXPOSURE_STATUS, 1, timeleft);
+}
+
+/**
+ Set the temperature of a given camera. This function sets the
+ temperature of the CCD camera \texttt{dev} to \texttt{temperature}
+ degrees Celsius. The valid range of the \texttt{temperature}
+ parameter is from -55 C to 45 C.
+
+ @param dev Camera device to set the temperature of.
+
+ @param temperature Temperature in Celsius to set CCD camera cold finger to.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetTemperature
+*/
+LIBFLIAPI FLISetTemperature(flidev_t dev, double temperature)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_TEMPERATURE, 1,
+ &temperature);
+}
+
+/**
+ Get the temperature of a given camera. This function places the
+ temperature of the CCD camera cold finger of device \texttt{dev} in
+ the location pointed to by \texttt{temperature}.
+
+ @param dev Camera device to get the temperature of.
+
+ @param temperature Pointer to where the temperature will be placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLISetTemperature
+*/
+LIBFLIAPI FLIGetTemperature(flidev_t dev, double *temperature)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_TEMPERATURE, 1, temperature);
+}
+
+/**
+ Grab a row of an image. This function grabs the next available row
+ of the image from camera device \texttt{dev}. The row of width
+ \texttt{width} is placed in the buffer pointed to by \texttt{buff}.
+ The size of the buffer pointed to by \texttt{buff} must take into
+ account the bit depth of the image, meaning the buffer size must be
+ at least \texttt{width} bytes for an 8-bit image, and at least
+ 2*\texttt{width} for a 16-bit image.
+
+ @param dev Camera whose image to grab the next available row from.
+
+ @param buff Pointer to where the next available row will be placed.
+
+ @param width Row width in pixels.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGrabFrame
+*/
+LIBFLIAPI FLIGrabRow(flidev_t dev, void *buff, size_t width)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GRAB_ROW, 2, buff, &width);
+}
+
+/**
+ Expose a frame for a given camera. This function exposes a frame
+ according to the settings (image area, exposure time, bit depth,
+ etc.) of camera \texttt{dev}. The settings of \texttt{dev} must be
+ valid for the camera device. They are set by calling the
+ appropriate set library functions. This function returns after the
+ exposure has started.
+
+ @param dev Camera to expose the frame of.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLISetExposureTime
+ @see FLISetFrameType
+ @see FLISetImageArea
+ @see FLISetHBin
+ @see FLISetVBin
+ @see FLISetNFlushes
+ @see FLISetBitDepth
+ @see FLIGrabFrame
+ @see FLICancelExposure
+ @see FLIGetExposureStatus
+*/
+LIBFLIAPI FLIExposeFrame(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_EXPOSE_FRAME, 0);
+}
+
+/**
+ Flush rows of a given camera. This function flushes \texttt{rows}
+ rows of camera \texttt{dev} \texttt{repeat} times.
+
+ @param dev Camera to flush rows of.
+
+ @param rows Number of rows to flush.
+
+ @param repeat Number of times to flush each row.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLISetNFlushes
+*/
+LIBFLIAPI FLIFlushRow(flidev_t dev, long rows, long repeat)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_FLUSH_ROWS, 2, &rows, &repeat);
+}
+
+/**
+ Set the number of flushes for a given camera. This function sets
+ the number of times the CCD array of camera \texttt{dev} is flushed
+ \emph{before} exposing a frame to \texttt{nflushes}. The valid
+ range of the \texttt{nflushes} parameter is from 1 to 16.
+
+ @param dev Camera to set the number of flushes of.
+
+ @param nflushes Number of times to flush CCD array before an
+ exposure.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIFlushRow
+ @see FLIExposeFrame
+*/
+LIBFLIAPI FLISetNFlushes(flidev_t dev, long nflushes)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_FLUSHES, 1, &nflushes);
+}
+
+/**
+ Set the gray-scale bit depth for a given camera. This function
+ sets the gray-scale bit depth of camera \texttt{dev} to
+ \texttt{bitdepth}. The \texttt{bitdepth} parameter is either
+ \texttt{FLI_MODE_8BIT} for 8-bit mode or \texttt{FLI_MODE_16BIT}
+ for 16-bit mode.
+
+ @param dev Camera to set the bit depth of.
+
+ @param bitdepth Gray-scale bit depth: \texttt{FLI_MODE_8BIT} or
+ \texttt{FLI_MODE_16BIT}.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see flibitdepth_t
+ @see FLIExposeFrame
+*/
+LIBFLIAPI FLISetBitDepth(flidev_t dev, flibitdepth_t bitdepth)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_BIT_DEPTH, 1, &bitdepth);
+}
+
+/**
+ Read the I/O port of a given camera. This function reads the I/O
+ port on camera \texttt{dev} and places the value in the location
+ pointed to by \texttt{ioportset}.
+
+ @param dev Camera to read the I/O port of.
+
+ @param ioportset Pointer to where the I/O port data will be stored.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIWriteIOPort
+ @see FLIConfigureIOPort
+*/
+LIBFLIAPI FLIReadIOPort(flidev_t dev, long *ioportset)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_READ_IOPORT, 1, ioportset);
+}
+
+/**
+ Write to the I/O port of a given camera. This function writes the
+ value \texttt{ioportset} to the I/O port on camera \texttt{dev}.
+
+ @param dev Camera to write I/O port of.
+
+ @param ioportset Data to be written to the I/O port.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIReadIOPort
+ @see FLIConfigureIOPort
+*/
+LIBFLIAPI FLIWriteIOPort(flidev_t dev, long ioportset)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_WRITE_IOPORT, 1, &ioportset);
+}
+
+/**
+ Configure the I/O port of a given camera. This function configures
+ the I/O port on camera \texttt{dev} with the value
+ \texttt{ioportset}.
+
+ The I/O configuration of each pin on a given camera is determined by the
+ value of \texttt{ioportset}. Setting a respective I/O bit enables the
+ port bit for output while clearing an I/O bit enables to port bit for
+ input. By default, all I/O ports are configured as inputs.
+
+ @param dev Camera to configure the I/O port of.
+
+ @param ioportset Data to configure the I/O port with.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIReadIOPort
+ @see FLIWriteIOPort
+*/
+LIBFLIAPI FLIConfigureIOPort(flidev_t dev, long ioportset)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_CONFIGURE_IOPORT, 1,
+ &ioportset);
+}
+
+/**
+ Lock a specified device. This function establishes an exclusive
+ lock (mutex) on the given device to prevent access to the device by
+ any other function or process.
+
+ @param dev Device to lock.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIUnlockDevice
+*/
+LIBFLIAPI FLILockDevice(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_lock(dev);
+}
+
+/**
+ Unlock a specified device. This function releases a previously
+ established exclusive lock (mutex) on the given device to allow
+ access to the device by any other function or process.
+
+ @param dev Device to unlock.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLILockDevice
+*/
+LIBFLIAPI FLIUnlockDevice(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_unlock(dev);
+}
+
+/**
+ Control the shutter on a given camera. This function controls the
+ shutter function on camera \texttt{dev} according to the
+ \texttt{shutter} parameter.
+
+ @param dev Device to control the shutter of.
+
+ @param shutter How to control the shutter. A value of
+ \texttt{FLI_SHUTTER_CLOSE} closes the shutter and
+ \texttt{FLI_SHUTTER_OPEN} opens the shutter.
+ \texttt{FLI_SHUTTER_EXTERNAL_TRIGGER_LOW} causes the exposure to begin
+ only when a logic LOW is detected on I/O port bit 0.
+ \texttt{FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH} causes the exposure to begin
+ only when a logic HIGH is detected on I/O port bit 0. This setting
+ may not be available on all cameras.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see flishutter_t
+*/
+LIBFLIAPI FLIControlShutter(flidev_t dev, flishutter_t shutter)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_CONTROL_SHUTTER, 1, &shutter);
+}
+
+/**
+ Enables background flushing of CCD array. This function enables the
+ background flushing of the CCD array camera \texttt{dev} according to the
+ \texttt{bgflush} parameter. Note that this function may not succeed
+ on all FLI products as this feature may not be available.
+
+ @param dev Device to control the background flushing of.
+
+ @param bgflush Enables or disables background flushing. A value of
+ \texttt{FLI_BGFLUSH_START} begins background flushing. It is important to
+ note that background flushing is stopped whenever \texttt{FLIExposeFrame()}
+ or \texttt{FLIControlShutter()} are called. \texttt{FLI_BGFLUSH_STOP} stops all
+ background flush activity.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see flibgflush_t
+*/
+LIBFLIAPI FLIControlBackgroundFlush(flidev_t dev, flibgflush_t bgflush)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_CONTROL_BGFLUSH, 1, &bgflush);
+}
+
+/**
+ List available devices. This function returns a pointer to a NULL
+ terminated list of device names. The pointer should be freed later
+ with \texttt{FLIFreeList()}. Each device name in the returned list
+ includes the filename needed by \texttt{FLIOpen()}, a separating
+ semicolon, followed by the model name or user assigned device name.
+
+ @param domain Domain to list the devices of. This is a bitwise
+ ORed combination of interface method and device type. Valid
+ interfaces include \texttt{FLIDOMAIN_PARALLEL_PORT},
+ \texttt{FLIDOMAIN_USB}, \texttt{FLIDOMAIN_SERIAL}, and
+ \texttt{FLIDOMAIN_INET}. Valid device types include
+ \texttt{FLIDEVICE_CAMERA}, \texttt{FLIDOMAIN_FILTERWHEEL}, and
+ \texttt{FLIDOMAIN_FOCUSER}.
+
+ @param names Pointer to where the device name list will be placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see flidomain_t
+ @see FLIFreeList
+ @see FLIOpen
+*/
+LIBFLIAPI FLIList(flidomain_t domain, char ***names)
+{
+ debug(FLIDEBUG_INFO, "FLIList() domain %04x", domain);
+ return fli_list(domain, names);
+}
+
+/**
+ Free a previously generated device list. Use this function after
+ \texttt{FLIList()} to free the list of device names.
+
+ @param names Pointer to the list.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIList
+*/
+LIBFLIAPI FLIFreeList(char **names)
+{
+ return fli_freelist(names);
+}
+
+/**
+ Set the filter wheel position of a given device. Use this function
+ to set the filter wheel position of \texttt{dev} to
+ \texttt{filter}.
+
+ @param dev Filter wheel device handle.
+
+ @param filter Desired filter wheel position.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetFilterPos
+*/
+LIBFLIAPI FLISetFilterPos(flidev_t dev, long filter)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_SET_FILTER_POS, 1, &filter);
+}
+
+/**
+ Get the filter wheel position of a given device. Use this function
+ to get the filter wheel position of \texttt{dev}.
+
+ @param dev Filter wheel device handle.
+
+ @param filter Pointer to where the filter wheel position will be
+ placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLISetFilterPos
+*/
+LIBFLIAPI FLIGetFilterPos(flidev_t dev, long *filter)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_FILTER_POS, 1, filter);
+}
+
+/**
+ Get the filter wheel filter count of a given device. Use this
+ function to get the filter count of filter wheel \texttt{dev}.
+
+ @param dev Filter wheel device handle.
+
+ @param filter Pointer to where the filter wheel filter count will
+ be placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+*/
+LIBFLIAPI FLIGetFilterCount(flidev_t dev, long *filter)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_FILTER_COUNT, 1, filter);
+}
+
+/**
+ Step the filter wheel or focuser motor of a given device. Use this
+ function to move the focuser or filter wheel \texttt{dev} by an
+ amount \texttt{steps}.
+
+ @param dev Filter wheel or focuser device handle.
+
+ @param steps Number of steps to move the focuser or filter wheel.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIGetStepperPosition
+*/
+LIBFLIAPI FLIStepMotor(flidev_t dev, long steps)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_STEP_MOTOR, 1, &steps);
+}
+
+/**
+ Get the stepper motor position of a given device. Use this
+ function to read the stepper motor position of filter wheel or
+ focuser \texttt{dev}.
+
+ @param dev Filter wheel or focuser device handle.
+
+ @param position Pointer to where the postion of the stepper motor
+ will be placed.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIStepMotor
+*/
+LIBFLIAPI FLIGetStepperPosition(flidev_t dev, long *position)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_GET_STEPPER_POS, 1, position);
+}
+
+/**
+ Home a given focuser. Use this function to home focuser
+ \texttt{dev}.
+
+ @param dev Focuser device handle.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+*/
+LIBFLIAPI FLIHomeFocuser(flidev_t dev)
+{
+ CHKDEVICE(dev);
+
+ return DEVICE->fli_command(dev, FLI_HOME_FOCUSER, 0);
+}
+
+/* This stuff is used by the next four functions */
+
+typedef struct list {
+ char *filename;
+ char *name;
+ long domain;
+ struct list *next;
+} list_t;
+
+static list_t *firstdevice = NULL;
+static list_t *currentdevice = NULL;
+
+/**
+ Creates a list of all devices within a specified
+ \texttt{domain}. Use \texttt{FLIDeleteList()} to delete the list
+ created with this function. This function is the first called begin
+ the iteration through the list of current FLI devices attached.
+
+ @param domain Domain to search for devices, set to zero to search all domains.
+ This parameter must contain the device type.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLIDeleteList
+ @see FLIListFirst
+ @see FLIListNext
+*/
+LIBFLIAPI FLICreateList(flidomain_t domain)
+{
+ char **list;
+ flidomain_t domord[5];
+ int i, j, k;
+
+ for (i = 0; i < 5; i++)
+ {
+ domord[i] = 0;
+ }
+
+ if (firstdevice != NULL)
+ {
+ FLIDeleteList();
+ }
+ currentdevice = NULL;
+
+ if ((domain & 0x00ff) != 0)
+ {
+ domord[0] = domain;
+ }
+ else
+ {
+ domord[0] = domain | FLIDOMAIN_PARALLEL_PORT;
+ domord[1] = domain | FLIDOMAIN_USB;
+ domord[2] = domain | FLIDOMAIN_SERIAL;
+ }
+
+ i = 0;
+ while (domord[i] != 0)
+ {
+ debug(FLIDEBUG_INFO, "Searching for domain 0x%04x.", domord[i]);
+ FLIList(domord[i], &list);
+ if (list != NULL)
+ {
+ j = 0;
+ while (list[j] != NULL)
+ {
+ if (firstdevice == NULL)
+ {
+ firstdevice = (list_t *)xmalloc(sizeof(list_t));
+ if (firstdevice == NULL)
+ return -ENOMEM;
+ currentdevice = firstdevice;
+ }
+ else
+ {
+ currentdevice->next = (list_t *) xmalloc(sizeof(list_t));
+ if (currentdevice->next == NULL)
+ return -ENOMEM;
+ currentdevice = currentdevice->next;
+ }
+ currentdevice->next = NULL;
+ currentdevice->domain = domord[i];
+ currentdevice->filename = NULL;
+ currentdevice->name = NULL;
+
+ k = 0;
+ while (k < (int) strlen(list[j]))
+ {
+ if (list[j][k] == ';')
+ {
+ currentdevice->filename = (char *) xmalloc(k+1);
+ if (currentdevice->filename != NULL)
+ {
+ strncpy(currentdevice->filename, list[j], k);
+ currentdevice->filename[k] = '\0';
+ }
+ currentdevice->name = (char *) xmalloc(strlen(&list[j][k+1]) + 1);
+ if (currentdevice->name != NULL)
+ {
+ strcpy(currentdevice->name, &list[j][k+1]);
+ }
+ break;
+ }
+ k++;
+ }
+ j++;
+ }
+ FLIFreeList(list);
+ }
+ i++;
+ }
+ return 0;
+}
+
+/**
+ Deletes a list of devices created by \texttt{FLICreateList()}.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLICreateList
+ @see FLIListFirst
+ @see FLIListNext
+*/
+LIBFLIAPI FLIDeleteList(void)
+{
+ list_t *dev = firstdevice;
+ list_t *last;
+
+ while (dev != NULL)
+ {
+ if (dev->filename != NULL)
+ xfree(dev->filename);
+ if (dev->name != NULL)
+ xfree(dev->name);
+ last = dev;
+ dev = dev->next;
+ xfree(last);
+ }
+
+ firstdevice = NULL;
+ currentdevice = NULL;
+
+ return 0;
+}
+
+/**
+ Obtains the first device in the list. Use this function to
+ get the first \texttt{domain}, \texttt{filename} and \texttt{name}
+ from the list of attached FLI devices created using
+ the function \texttt{FLICreateList()}. Use
+ \texttt{FLIListNext()} to obtain more found devices.
+
+ @param domain Pointer to where to domain of the device will be placed.
+
+ @param filename Pointer to where the filename of the device will be placed.
+
+ @param fnlen Length of the supplied buffer to hold the filename.
+
+ @param name Pointer to where the name of the device will be placed.
+
+ @param namelen Length of the supplied buffer to hold the name.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLICreateList
+ @see FLIDeleteList
+ @see FLIListNext
+*/
+LIBFLIAPI FLIListFirst(flidomain_t *domain, char *filename,
+ size_t fnlen, char *name, size_t namelen)
+{
+ currentdevice = firstdevice;
+ return FLIListNext(domain, filename, fnlen, name, namelen);
+}
+
+/**
+ Obtains the next device in the list. Use this function to
+ get the next \texttt{domain}, \texttt{filename} and \texttt{name}
+ from the list of attached FLI devices created using
+ the function \texttt{FLICreateList()}.
+
+ @param domain Pointer to where to domain of the device will be placed.
+
+ @param filename Pointer to where the filename of the device will be placed.
+
+ @param fnlen Length of the supplied buffer to hold the filename.
+
+ @param name Pointer to where the name of the device will be placed.
+
+ @param namelen Length of the supplied buffer to hold the name.
+
+ @return Zero on success.
+ @return Non-zero on failure.
+
+ @see FLICreateList
+ @see FLIDeleteList
+ @see FLIListFirst
+*/
+LIBFLIAPI FLIListNext(flidomain_t *domain, char *filename,
+ size_t fnlen, char *name, size_t namelen)
+{
+ if (currentdevice == NULL)
+ {
+ *domain = 0;
+ filename[0] = '\0';
+ name[0] = '\0';
+ return -EBADF;
+ }
+
+ *domain = currentdevice->domain;
+ strncpy(filename, currentdevice->filename, fnlen);
+ filename[fnlen-1] = '\0';
+ strncpy(name, currentdevice->name, namelen);
+ name[namelen-1] = '\0';
+
+ currentdevice = currentdevice->next;
+ return 0;
+}
diff --git a/kstars/kstars/indi/fli/libfli.h b/kstars/kstars/indi/fli/libfli.h
new file mode 100644
index 00000000..351a9e8e
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli.h
@@ -0,0 +1,214 @@
+/*
+
+ 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
+
+*/
+
+#ifndef _LIBFLI_H_
+#define _LIBFLI_H_
+
+#include <sys/types.h>
+
+/**
+ An opaque handle used by library functions to refer to FLI
+ hardware.
+*/
+typedef long flidev_t;
+
+/**
+ The domain of an FLI device. This consists of a bitwise ORed
+ combination of interface method and device type. Valid interfaces
+ are \texttt{FLIDOMAIN_PARALLEL_PORT}, \texttt{FLIDOMAIN_USB},
+ \texttt{FLIDOMAIN_SERIAL}, and \texttt{FLIDOMAIN_INET}. Valid
+ device types are \texttt{FLIDEVICE_CAMERA},
+ \texttt{FLIDOMAIN_FILTERWHEEL}, and \texttt{FLIDOMAIN_FOCUSER}.
+
+ @see FLIOpen
+ @see FLIList
+ */
+typedef long flidomain_t;
+
+#define FLIDOMAIN_NONE (0x00)
+#define FLIDOMAIN_PARALLEL_PORT (0x01)
+#define FLIDOMAIN_USB (0x02)
+#define FLIDOMAIN_SERIAL (0x03)
+#define FLIDOMAIN_INET (0x04)
+
+#define FLIDEVICE_NONE (0x000)
+#define FLIDEVICE_CAMERA (0x100)
+#define FLIDEVICE_FILTERWHEEL (0x200)
+#define FLIDEVICE_FOCUSER (0x300)
+
+/**
+ The frame type for an FLI CCD camera device. Valid frame types are
+ \texttt{FLI_FRAME_TYPE_NORMAL} and \texttt{FLI_FRAME_TYPE_DARK}.
+
+ @see FLISetFrameType
+*/
+typedef long fliframe_t;
+
+#define FLI_FRAME_TYPE_NORMAL (0)
+#define FLI_FRAME_TYPE_DARK (1)
+
+/**
+ The gray-scale bit depth for an FLI camera device. Valid bit
+ depths are \texttt{FLI_MODE_8BIT} and \texttt{FLI_MODE_16BIT}.
+
+ @see FLISetBitDepth
+*/
+typedef long flibitdepth_t;
+
+#define FLI_MODE_8BIT (0)
+#define FLI_MODE_16BIT (1)
+
+/**
+ Type used for shutter operations for an FLI camera device. Valid
+ shutter types are \texttt{FLI_SHUTTER_CLOSE},
+ \texttt{FLI_SHUTTER_OPEN},
+ \texttt{FLI_SHUTTER_EXTERNAL_TRIGGER},
+ \texttt{FLI_SHUTTER_EXTERNAL_TRIGGER_LOW}, and
+ \texttt{FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH}.
+
+ @see FLIControlShutter
+*/
+typedef long flishutter_t;
+
+#define FLI_SHUTTER_CLOSE (0x0000)
+#define FLI_SHUTTER_OPEN (0x0001)
+#define FLI_SHUTTER_EXTERNAL_TRIGGER (0x0002)
+#define FLI_SHUTTER_EXTERNAL_TRIGGER_LOW (0x0002)
+#define FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH (0x0004)
+
+/**
+ Type used for background flush operations for an FLI camera device. Valid
+ bgflush types are \texttt{FLI_BGFLUSH_STOP} and
+ \texttt{FLI_BGFLUSH_START}.
+
+ @see FLIControlBackgroundFlush
+*/
+typedef long flibgflush_t;
+
+#define FLI_BGFLUSH_STOP (0x0000)
+#define FLI_BGFLUSH_START (0x0001)
+
+/**
+ Type specifying library debug levels. Valid debug levels are
+ \texttt{FLIDEBUG_NONE}, \texttt{FLIDEBUG_INFO},
+ \texttt{FLIDEBUG_WARN}, and \texttt{FLIDEBUG_FAIL}.
+
+ @see FLISetDebugLevel
+*/
+typedef long flidebug_t;
+
+#define FLIDEBUG_NONE (0x00)
+#define FLIDEBUG_INFO (0x01)
+#define FLIDEBUG_WARN (0x02)
+#define FLIDEBUG_FAIL (0x04)
+#define FLIDEBUG_ALL (FLIDEBUG_INFO | FLIDEBUG_WARN | FLIDEBUG_FAIL)
+
+#ifdef WIN32
+#ifndef LIBFLIAPI
+#define LIBFLIAPI __declspec(dllimport) long __stdcall
+#endif
+#else
+#define LIBFLIAPI long
+#endif
+
+/* Library API Function prototypes */
+
+#ifdef __cplusplus
+extern "C" { // only need to export C interface if used by C++ source code
+#endif
+
+LIBFLIAPI FLIOpen(flidev_t *dev, char *name, flidomain_t domain);
+LIBFLIAPI FLISetDebugLevel(char *host, flidebug_t level);
+LIBFLIAPI FLIClose(flidev_t dev);
+LIBFLIAPI FLIGetLibVersion(char* ver, size_t len);
+LIBFLIAPI FLIGetModel(flidev_t dev, char* model, size_t len);
+LIBFLIAPI FLIGetPixelSize(flidev_t dev, double *pixel_x, double *pixel_y);
+LIBFLIAPI FLIGetHWRevision(flidev_t dev, long *hwrev);
+LIBFLIAPI FLIGetFWRevision(flidev_t dev, long *fwrev);
+LIBFLIAPI FLIGetArrayArea(flidev_t dev, long* ul_x, long* ul_y,
+ long* lr_x, long* lr_y);
+LIBFLIAPI FLIGetVisibleArea(flidev_t dev, long* ul_x, long* ul_y,
+ long* lr_x, long* lr_y);
+LIBFLIAPI FLISetExposureTime(flidev_t dev, long exptime);
+LIBFLIAPI FLISetImageArea(flidev_t dev, long ul_x, long ul_y,
+ long lr_x, long lr_y);
+LIBFLIAPI FLISetHBin(flidev_t dev, long hbin);
+LIBFLIAPI FLISetVBin(flidev_t dev, long vbin);
+LIBFLIAPI FLISetFrameType(flidev_t dev, fliframe_t frametype);
+LIBFLIAPI FLICancelExposure(flidev_t dev);
+LIBFLIAPI FLIGetExposureStatus(flidev_t dev, long *timeleft);
+LIBFLIAPI FLISetTemperature(flidev_t dev, double temperature);
+LIBFLIAPI FLIGetTemperature(flidev_t dev, double *temperature);
+LIBFLIAPI FLIGrabRow(flidev_t dev, void *buff, size_t width);
+LIBFLIAPI FLIExposeFrame(flidev_t dev);
+LIBFLIAPI FLIFlushRow(flidev_t dev, long rows, long repeat);
+LIBFLIAPI FLISetNFlushes(flidev_t dev, long nflushes);
+LIBFLIAPI FLISetBitDepth(flidev_t dev, flibitdepth_t bitdepth);
+LIBFLIAPI FLIReadIOPort(flidev_t dev, long *ioportset);
+LIBFLIAPI FLIWriteIOPort(flidev_t dev, long ioportset);
+LIBFLIAPI FLIConfigureIOPort(flidev_t dev, long ioportset);
+LIBFLIAPI FLILockDevice(flidev_t dev);
+LIBFLIAPI FLIUnlockDevice(flidev_t dev);
+LIBFLIAPI FLIControlShutter(flidev_t dev, flishutter_t shutter);
+LIBFLIAPI FLIControlBackgroundFlush(flidev_t dev, flibgflush_t bgflush);
+LIBFLIAPI FLIList(flidomain_t domain, char ***names);
+LIBFLIAPI FLIFreeList(char **names);
+LIBFLIAPI FLISetFilterPos(flidev_t dev, long filter);
+LIBFLIAPI FLIGetFilterPos(flidev_t dev, long *filter);
+LIBFLIAPI FLIGetFilterCount(flidev_t dev, long *filter);
+LIBFLIAPI FLIStepMotor(flidev_t dev, long steps);
+LIBFLIAPI FLIGetStepperPosition(flidev_t dev, long *position);
+LIBFLIAPI FLIHomeFocuser(flidev_t dev);
+LIBFLIAPI FLICreateList(flidomain_t domain);
+LIBFLIAPI FLIDeleteList(void);
+LIBFLIAPI FLIListFirst(flidomain_t *domain, char *filename,
+ size_t fnlen, char *name, size_t namelen);
+LIBFLIAPI FLIListNext(flidomain_t *domain, char *filename,
+ size_t fnlen, char *name, size_t namelen);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBFLI_H_ */
diff --git a/kstars/kstars/indi/fli/libfli.pdf b/kstars/kstars/indi/fli/libfli.pdf
new file mode 100644
index 00000000..f5fb45f5
--- /dev/null
+++ b/kstars/kstars/indi/fli/libfli.pdf
Binary files differ
diff --git a/kstars/kstars/indi/fli/readme.txt b/kstars/kstars/indi/fli/readme.txt
new file mode 100644
index 00000000..1f3b8925
--- /dev/null
+++ b/kstars/kstars/indi/fli/readme.txt
@@ -0,0 +1,15 @@
+Current Version 1.11
+
+Changes since 1.1
+ - Corrected documentation for function FLIConfigureIOPort()
+ - Added some bounds checking on FLISetImageArea()
+ Note that on cameras with a FWRev < 0x0300 exceeding the set image
+ area will lead to VERY SLOW grabs
+ - Added some bounds checking on FLIGrabRow()
+ - Removed function FLIGrabFrame(), it was never supported anyways
+ - Added FLI_SHUTTER_EXTERNAL_TRIGGER to documentation for FLIControlShutter()
+ - Added FLI_SHUTTER_EXTERNAL_TRIGGER_LOW and FLI_SHUTTER_EXTERNAL_TRIGGER_HIGH
+ - Added FLIStartBackgroundFlush()
+ - Repaired temperature settungs under Linux
+ - Made temperature conversion more portable
+
diff --git a/kstars/kstars/indi/fli_ccd.c b/kstars/kstars/indi/fli_ccd.c
new file mode 100644
index 00000000..4fa9a95a
--- /dev/null
+++ b/kstars/kstars/indi/fli_ccd.c
@@ -0,0 +1,1435 @@
+#if 0
+ FLI CCD
+ INDI Interface for Finger Lakes Instruments CCDs
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <zlib.h>
+
+#include "fli/libfli.h"
+#include "fitsrw.h"
+#include "indidevapi.h"
+#include "eventloop.h"
+#include "indicom.h"
+
+void ISInit(void);
+void getBasicData(void);
+void ISPoll(void *);
+void handleExposure(void *);
+void connectCCD(void);
+void getBasicData(void);
+void uploadFile(const char* filename);
+int writeFITS(const char* filename, char errmsg[]);
+int findcam(flidomain_t domain);
+int setImageArea(char errmsg[]);
+int manageDefaults(char errmsg[]);
+int grabImage(void);
+int checkPowerS(ISwitchVectorProperty *sp);
+int checkPowerN(INumberVectorProperty *np);
+int checkPowerT(ITextVectorProperty *tp);
+int getOnSwitch(ISwitchVectorProperty *sp);
+int isCCDConnected(void);
+
+double min(void);
+double max(void);
+FITS_HDU_LIST * create_fits_header (FITS_FILE *ofp, uint width, uint height, uint bpp);
+
+extern char* me;
+extern int errno;
+
+#define mydev "FLI CCD"
+
+#define COMM_GROUP "Communication"
+#define EXPOSE_GROUP "Expose"
+#define IMAGE_GROUP "Image Settings"
+#define DATA_GROUP "Data Channel"
+
+#define MAX_CCD_TEMP 45 /* Max CCD temperature */
+#define MIN_CCD_TEMP -55 /* Min CCD temperature */
+#define MAX_X_BIN 16. /* Max Horizontal binning */
+#define MAX_Y_BIN 16. /* Max Vertical binning */
+#define MAX_PIXELS 4096 /* Max number of pixels in one dimension */
+#define POLLMS 1000 /* Polling time (ms) */
+#define TEMP_THRESHOLD .25 /* Differential temperature threshold (C)*/
+#define NFLUSHES 1 /* Number of times a CCD array is flushed before an exposure */
+
+#define FILENAMESIZ 2048
+#define LIBVERSIZ 1024
+#define PREFIXSIZ 64
+#define PIPEBUFSIZ 8192
+#define FRAME_ILEN 64
+
+#define getBigEndian(p) ( ((p & 0xff) << 8) | (p >> 8))
+
+enum FLIFrames { LIGHT_FRAME = 0, BIAS_FRAME, DARK_FRAME, FLAT_FRAME };
+
+
+typedef struct {
+ flidomain_t domain;
+ char *dname;
+ char *name;
+ char *model;
+ long HWRevision;
+ long FWRevision;
+ double x_pixel_size;
+ double y_pixel_size;
+ long Array_Area[4];
+ long Visible_Area[4];
+ int width, height;
+ double temperature;
+} cam_t;
+
+typedef struct {
+int width;
+int height;
+int frameType;
+int expose;
+unsigned short *img;
+} img_t;
+
+/*static int streamTimerID; Stream ID */
+
+static flidev_t fli_dev;
+static cam_t *FLICam;
+static img_t *FLIImg;
+static int portSwitchIndex;
+
+long int Domains[] = { FLIDOMAIN_USB, FLIDOMAIN_SERIAL, FLIDOMAIN_PARALLEL_PORT, FLIDOMAIN_INET };
+
+/*INDI controls */
+
+/* Connect/Disconnect */
+static ISwitch PowerS[] = {{"CONNECT" , "Connect" , ISS_OFF, 0, 0},{"DISCONNECT", "Disconnect", ISS_ON, 0, 0}};
+static ISwitchVectorProperty PowerSP = { mydev, "CONNECTION" , "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE, PowerS, NARRAY(PowerS), "", 0};
+
+/* Types of Ports */
+static ISwitch PortS[] = {{"USB", "", ISS_ON, 0, 0}, {"Serial", "", ISS_OFF, 0, 0}, {"Parallel", "", ISS_OFF, 0, 0}, {"INet", "", ISS_OFF, 0, 0}};
+static ISwitchVectorProperty PortSP = { mydev, "Port Type", "", COMM_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, PortS, NARRAY(PortS), "", 0};
+
+/* Types of Frames */
+static ISwitch FrameTypeS[] = { {"FRAME_LIGHT", "Light", ISS_ON, 0, 0}, {"FRAME_BIAS", "Bias", ISS_OFF, 0, 0}, {"FRAME_DARK", "Dark", ISS_OFF, 0, 0}, {"FRAME_FLAT", "Flat Field", ISS_OFF, 0, 0}};
+static ISwitchVectorProperty FrameTypeSP = { mydev, "CCD_FRAME_TYPE", "Frame Type", EXPOSE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, FrameTypeS, NARRAY(FrameTypeS), "", 0};
+
+/* Frame coordinates. Full frame is default */
+static INumber FrameN[] = {
+ { "X", "X", "%.0f", 0., MAX_PIXELS, 1., 0., 0, 0, 0},
+ { "Y", "Y", "%.0f", 0., MAX_PIXELS, 1., 0., 0, 0, 0},
+ { "WIDTH", "Width", "%.0f", 0., MAX_PIXELS, 1., 0., 0, 0, 0},
+ { "HEIGHT", "Height", "%.0f",0., MAX_PIXELS, 1., 0., 0, 0, 0}};
+ static INumberVectorProperty FrameNP = { mydev, "CCD_FRAME", "Frame", IMAGE_GROUP, IP_RW, 60, IPS_IDLE, FrameN, NARRAY(FrameN), "", 0};
+
+ /* Binning */
+ static INumber BinningN[] = {
+ { "HOR_BIN", "X", "%0.f", 1., MAX_X_BIN, 1., 1., 0, 0, 0},
+ { "VER_BIN", "Y", "%0.f", 1., MAX_Y_BIN, 1., 1., 0, 0, 0}};
+ static INumberVectorProperty BinningNP = { mydev, "CCD_BINNING", "Binning", IMAGE_GROUP, IP_RW, 60, IPS_IDLE, BinningN, NARRAY(BinningN), "", 0};
+
+ /* Exposure time */
+ static INumber ExposeTimeN[] = {{ "EXPOSE_DURATION", "Duration (s)", "%5.2f", 0., 36000., .5, 1., 0, 0, 0}};
+ static INumberVectorProperty ExposeTimeNP = { mydev, "CCD_EXPOSE_DURATION", "Expose", EXPOSE_GROUP, IP_RW, 60, IPS_IDLE, ExposeTimeN, NARRAY(ExposeTimeN), "", 0};
+
+ /* Temperature control */
+ static INumber TemperatureN[] = { {"TEMPERATURE", "Temperature", "%+06.2f", MIN_CCD_TEMP, MAX_CCD_TEMP, .2, 0., 0, 0, 0}};
+ static INumberVectorProperty TemperatureNP = { mydev, "CCD_TEMPERATURE", "Temperature (C)", EXPOSE_GROUP, IP_RW, 60, IPS_IDLE, TemperatureN, NARRAY(TemperatureN), "", 0};
+
+ /* Pixel size (µm) */
+static INumber PixelSizeN[] = {
+ { "Width", "", "%.0f", 0. , 0., 0., 0., 0, 0, 0},
+ { "Height", "", "%.0f", 0. , 0., 0., 0., 0, 0, 0}};
+static INumberVectorProperty PixelSizeNP = { mydev, "Pixel Size (µm)", "", DATA_GROUP, IP_RO, 0, IPS_IDLE, PixelSizeN, NARRAY(PixelSizeN), "", 0};
+
+/* BLOB for sending image */
+static IBLOB imageB = {"CCD1", "Feed", "", 0, 0, 0, 0, 0, 0, 0};
+static IBLOBVectorProperty imageBP = {mydev, "Video", "Video", COMM_GROUP,
+ IP_RO, 0, IPS_IDLE, &imageB, 1, "", 0};
+
+/* send client definitions of all properties */
+void ISInit()
+{
+ static int isInit=0;
+
+ if (isInit)
+ return;
+
+ /* USB by default {USB, SERIAL, PARALLEL, INET} */
+ portSwitchIndex = 0;
+
+ FLIImg = malloc (sizeof(img_t));
+
+ if (FLIImg == NULL)
+ {
+ IDMessage(mydev, "Error: unable to initialize driver. Low memory.");
+ IDLog("Error: unable to initialize driver. Low memory.");
+ return;
+ }
+
+ IEAddTimer (POLLMS, ISPoll, NULL);
+
+ isInit = 1;
+
+}
+
+void ISGetProperties (const char *dev)
+{
+
+ ISInit();
+
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ /* COMM_GROUP */
+ IDDefSwitch(&PowerSP, NULL);
+ IDDefSwitch(&PortSP, NULL);
+ IDDefBLOB(&imageBP, NULL);
+
+ /* Expose */
+ IDDefSwitch(&FrameTypeSP, NULL);
+ IDDefNumber(&ExposeTimeNP, NULL);
+ IDDefNumber(&TemperatureNP, NULL);
+
+ /* Image Group */
+ IDDefNumber(&FrameNP, NULL);
+ IDDefNumber(&BinningNP, NULL);
+
+}
+
+void ISNewBLOB (const char *dev, const char *name, int sizes[], char *blobs[], char *formats[], char *names[], int n)
+{
+ dev=dev;name=name;sizes=sizes;blobs=blobs;formats=formats;names=names;n=n;
+}
+
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ long err;
+ int i;
+ ISwitch *sp;
+
+ /* ignore if not ours */
+ if (dev && strcmp (dev, mydev))
+ return;
+
+ ISInit();
+
+ /* Port type */
+ if (!strcmp (name, PortSP.name))
+ {
+ PortSP.s = IPS_IDLE;
+ IUResetSwitches(&PortSP);
+ IUUpdateSwitches(&PortSP, states, names, n);
+ portSwitchIndex = getOnSwitch(&PortSP);
+
+ PortSP.s = IPS_OK;
+ IDSetSwitch(&PortSP, NULL);
+ return;
+ }
+
+ /* Connection */
+ if (!strcmp (name, PowerSP.name))
+ {
+ IUResetSwitches(&PowerSP);
+ IUUpdateSwitches(&PowerSP, states, names, n);
+ connectCCD();
+ return;
+ }
+
+ /* Frame Type */
+ if (!strcmp(FrameTypeSP.name, name))
+ {
+ if (checkPowerS(&FrameTypeSP))
+ return;
+
+ FrameTypeSP.s = IPS_IDLE;
+
+ for (i = 0; i < n ; i++)
+ {
+ sp = IUFindSwitch(&FrameTypeSP, names[i]);
+
+ if (!sp)
+ {
+ IDSetSwitch(&FrameTypeSP, "Unknown error. %s is not a member of %s property.", names[0], name);
+ return;
+ }
+
+ /* NORMAL, BIAS, or FLAT */
+ if ( (sp == &FrameTypeS[LIGHT_FRAME] || sp == &FrameTypeS[FLAT_FRAME]) && states[i] == ISS_ON)
+ {
+ if (sp == &FrameTypeS[LIGHT_FRAME])
+ FLIImg->frameType = LIGHT_FRAME;
+ else
+ FLIImg->frameType = FLAT_FRAME;
+
+ if ((err = FLISetFrameType(fli_dev, FLI_FRAME_TYPE_NORMAL) ))
+ {
+ IUResetSwitches(&FrameTypeSP);
+ FrameTypeS[LIGHT_FRAME].s = ISS_ON;
+ IDSetSwitch(&FrameTypeSP, "FLISetFrameType() failed. %s.\n", strerror((int)-err));
+ IDLog("FLISetFrameType() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ IUResetSwitches(&FrameTypeSP);
+ sp->s = ISS_ON;
+ FrameTypeSP.s = IPS_OK;
+ IDSetSwitch(&FrameTypeSP, NULL);
+ break;
+ }
+ /* DARK AND BIAS */
+ else if ( (sp == &FrameTypeS[DARK_FRAME] || sp == &FrameTypeS[BIAS_FRAME]) && states[i] == ISS_ON)
+ {
+
+ if (sp == &FrameTypeS[DARK_FRAME])
+ FLIImg->frameType = DARK_FRAME;
+ else
+ FLIImg->frameType = BIAS_FRAME;
+
+ if ((err = FLISetFrameType(fli_dev, FLI_FRAME_TYPE_DARK) ))
+ {
+ IUResetSwitches(&FrameTypeSP);
+ FrameTypeS[LIGHT_FRAME].s = ISS_ON;
+ IDSetSwitch(&FrameTypeSP, "FLISetFrameType() failed. %s.\n", strerror((int)-err));
+ IDLog("FLISetFrameType() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ IUResetSwitches(&FrameTypeSP);
+ sp->s = ISS_ON;
+ FrameTypeSP.s = IPS_OK;
+ IDSetSwitch(&FrameTypeSP, NULL);
+ break;
+ }
+
+ } /* For loop */
+
+ return;
+ }
+
+}
+
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+ ISInit();
+
+ /* ignore if not ours */
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ /* suppress warning */
+ n=n; dev=dev; name=name; names=names; texts=texts;
+
+}
+
+
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ long err;
+ int i;
+ INumber *np;
+ char errmsg[ERRMSG_SIZE];
+
+ /* ignore if not ours */
+ if (dev && strcmp (dev, mydev))
+ return;
+
+ ISInit();
+
+ /* Exposure time */
+ if (!strcmp (ExposeTimeNP.name, name))
+ {
+ if (checkPowerN(&ExposeTimeNP))
+ return;
+
+ if (ExposeTimeNP.s == IPS_BUSY)
+ {
+ if ( (err = FLICancelExposure(fli_dev)))
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ IDSetNumber(&ExposeTimeNP, "FLICancelExposure() failed. %s.", strerror((int)-err));
+ IDLog("FLICancelExposure() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ ExposeTimeNP.s = IPS_IDLE;
+ ExposeTimeN[0].value = 0;
+
+ IDSetNumber(&ExposeTimeNP, "Exposure cancelled.");
+ IDLog("Exposure Cancelled.\n");
+ return;
+ }
+
+ ExposeTimeNP.s = IPS_IDLE;
+
+ np = IUFindNumber(&ExposeTimeNP, names[0]);
+
+ if (!np)
+ {
+ IDSetNumber(&ExposeTimeNP, "Error: %s is not a member of %s property.", names[0], name);
+ return;
+ }
+
+ np->value = values[0];
+ FLIImg->expose = (int) (values[0] * 1000.);
+
+ /* Set duration */
+ if ( (err = FLISetExposureTime(fli_dev, np->value * 1000.) ))
+ {
+ IDSetNumber(&ExposeTimeNP, "FLISetExposureTime() failed. %s.\n", strerror((int)-err));
+ IDLog("FLISetExposureTime() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ IDLog("Exposure Time (ms) is: %g\n", np->value * 1000.);
+
+ handleExposure(NULL);
+ return;
+ }
+
+
+ if (!strcmp(TemperatureNP.name, name))
+ {
+ if (checkPowerN(&TemperatureNP))
+ return;
+
+ TemperatureNP.s = IPS_IDLE;
+
+ np = IUFindNumber(&TemperatureNP, names[0]);
+
+ if (!np)
+ {
+ IDSetNumber(&TemperatureNP, "Unknown error. %s is not a member of %s property.", names[0], name);
+ return;
+ }
+
+ if (values[0] < MIN_CCD_TEMP || values[0] > MAX_CCD_TEMP)
+ {
+ IDSetNumber(&TemperatureNP, "Error: valid range of temperature is from %d to %d", MIN_CCD_TEMP, MAX_CCD_TEMP);
+ return;
+ }
+
+ if ( (err = FLISetTemperature(fli_dev, values[0])))
+ {
+ IDSetNumber(&TemperatureNP, "FLISetTemperature() failed. %s.", strerror((int)-err));
+ IDLog("FLISetTemperature() failed. %s.", strerror((int)-err));
+ return;
+ }
+
+ FLICam->temperature = values[0];
+ TemperatureNP.s = IPS_BUSY;
+
+ IDSetNumber(&TemperatureNP, "Setting CCD temperature to %+06.2f C", values[0]);
+ IDLog("Setting CCD temperature to %+06.2f C\n", values[0]);
+ return;
+ }
+
+ if (!strcmp(FrameNP.name, name))
+ {
+ int nset=0;
+
+ if (checkPowerN(&FrameNP))
+ return;
+
+ FrameNP.s = IPS_IDLE;
+
+ for (i=0; i < n ; i++)
+ {
+ np = IUFindNumber(&FrameNP, names[i]);
+
+ if (!np)
+ {
+ IDSetNumber(&FrameNP, "Unknown error. %s is not a member of %s property.", names[0], name);
+ return;
+ }
+
+ /* X or Width */
+ if (np == &FrameN[0] || np==&FrameN[2])
+ {
+ if (values[i] < 0 || values[i] > FLICam->width)
+ break;
+
+ nset++;
+ np->value = values[i];
+ }
+ /* Y or height */
+ else if (np == &FrameN[1] || np==&FrameN[3])
+ {
+ if (values[i] < 0 || values[i] > FLICam->height)
+ break;
+
+ nset++;
+ np->value = values[i];
+ }
+ }
+
+ if (nset < 4)
+ {
+ IDSetNumber(&FrameNP, "Invalid range. Valid range is (0,0) - (%0d,%0d)", FLICam->width, FLICam->height);
+ IDLog("Invalid range. Valid range is (0,0) - (%0d,%0d)", FLICam->width, FLICam->height);
+ return;
+ }
+
+ if (setImageArea(errmsg))
+ {
+ IDSetNumber(&FrameNP, "%s", errmsg);
+ return;
+ }
+
+ FrameNP.s = IPS_OK;
+
+ /* Adjusting image width and height */
+ FLIImg->width = FrameN[2].value;
+ FLIImg->height = FrameN[3].value;
+
+ IDSetNumber(&FrameNP, NULL);
+
+ } /* end FrameNP */
+
+
+ if (!strcmp(BinningNP.name, name))
+ {
+ if (checkPowerN(&BinningNP))
+ return;
+
+ BinningNP.s = IPS_IDLE;
+
+ for (i=0 ; i < n ; i++)
+ {
+ np = IUFindNumber(&BinningNP, names[i]);
+
+ if (!np)
+ {
+ IDSetNumber(&BinningNP, "Unknown error. %s is not a member of %s property.", names[0], name);
+ return;
+ }
+
+ /* X binning */
+ if (np == &BinningN[0])
+ {
+ if (values[i] < 1 || values[i] > MAX_X_BIN)
+ {
+ IDSetNumber(&BinningNP, "Error: Valid X bin values are from 1 to %g", MAX_X_BIN);
+ IDLog("Error: Valid X bin values are from 1 to %g", MAX_X_BIN);
+ return;
+ }
+
+ if ( (err = FLISetHBin(fli_dev, values[i])))
+ {
+ IDSetNumber(&BinningNP, "FLISetHBin() failed. %s.", strerror((int)-err));
+ IDLog("FLISetHBin() failed. %s.", strerror((int)-err));
+ return;
+ }
+
+ np->value = values[i];
+ }
+ else if (np == &BinningN[1])
+ {
+ if (values[i] < 1 || values[i] > MAX_Y_BIN)
+ {
+ IDSetNumber(&BinningNP, "Error: Valid Y bin values are from 1 to %g", MAX_Y_BIN);
+ IDLog("Error: Valid X bin values are from 1 to %g", MAX_Y_BIN);
+ return;
+ }
+
+ if ( (err = FLISetVBin(fli_dev, values[i])))
+ {
+ IDSetNumber(&BinningNP, "FLISetVBin() failed. %s.", strerror((int)-err));
+ IDLog("FLISetVBin() failed. %s.", strerror((int)-err));
+ return;
+ }
+
+ np->value = values[i];
+ }
+ } /* end for */
+
+ if (setImageArea(errmsg))
+ {
+ IDSetNumber(&BinningNP, errmsg, NULL);
+ IDLog("%s", errmsg);
+ return;
+ }
+
+ BinningNP.s = IPS_OK;
+
+ IDLog("Binning is: %.0f x %.0f\n", BinningN[0].value, BinningN[1].value);
+
+ IDSetNumber(&BinningNP, NULL);
+ return;
+ }
+
+}
+
+
+void ISPoll(void *p)
+{
+ long err;
+ long timeleft;
+ double ccdTemp;
+
+ if (!isCCDConnected())
+ {
+ IEAddTimer (POLLMS, ISPoll, NULL);
+ return;
+ }
+
+ /*IDLog("In Poll.\n");*/
+
+ switch (ExposeTimeNP.s)
+ {
+ case IPS_IDLE:
+ break;
+
+ case IPS_OK:
+ break;
+
+ case IPS_BUSY:
+ if ( (err = FLIGetExposureStatus(fli_dev, &timeleft)))
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ ExposeTimeN[0].value = 0;
+
+ IDSetNumber(&ExposeTimeNP, "FLIGetExposureStatus() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetExposureStatus() failed. %s.\n", strerror((int)-err));
+ break;
+ }
+
+ /*ExposeProgressN[0].value = (timeleft / 1000.);*/
+
+ if (timeleft > 0)
+ {
+ ExposeTimeN[0].value = timeleft / 1000.;
+ IDSetNumber(&ExposeTimeNP, NULL);
+ break;
+ }
+ /*{
+ IDSetNumber(&ExposeProgressNP, NULL);
+ break;
+ }*/
+
+ /* We're done exposing */
+ ExposeTimeNP.s = IPS_IDLE;
+ ExposeTimeN[0].value = 0;
+ /*ExposeProgressNP.s = IPS_IDLE;*/
+ IDSetNumber(&ExposeTimeNP, "Exposure done, downloading image...");
+ IDLog("Exposure done, downloading image...\n");
+ /*IDSetNumber(&ExposeProgressNP, NULL);*/
+
+ /* grab and save image */
+ if (grabImage())
+ break;
+
+ /* Multiple image exposure
+ if ( imagesLeft > 0)
+ {
+ IDMessage(mydev, "Image #%d will be taken in %0.f seconds.", imageCount+1, DelayN[0].value);
+ IDLog("Image #%d will be taken in %0.f seconds.", imageCount+1, DelayN[0].value);
+ IEAddTimer (DelayN[0].value * 1000., handleExposure, NULL);
+ }*/
+ break;
+
+ case IPS_ALERT:
+ break;
+ }
+
+ switch (TemperatureNP.s)
+ {
+ case IPS_IDLE:
+ case IPS_OK:
+ if ( (err = FLIGetTemperature(fli_dev, &ccdTemp)))
+ {
+ TemperatureNP.s = IPS_IDLE;
+ IDSetNumber(&TemperatureNP, "FLIGetTemperature() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetTemperature() failed. %s.", strerror((int)-err));
+ return;
+ }
+
+ if (fabs(TemperatureN[0].value - ccdTemp) >= TEMP_THRESHOLD)
+ {
+ TemperatureN[0].value = ccdTemp;
+ IDSetNumber(&TemperatureNP, NULL);
+ }
+ break;
+
+ case IPS_BUSY:
+ if ((err = FLIGetTemperature(fli_dev, &ccdTemp)))
+ {
+ TemperatureNP.s = IPS_ALERT;
+ IDSetNumber(&TemperatureNP, "FLIGetTemperature() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetTemperature() failed. %s.", strerror((int)-err));
+ return;
+ }
+
+ if (fabs(FLICam->temperature - ccdTemp) <= TEMP_THRESHOLD)
+ TemperatureNP.s = IPS_OK;
+
+ TemperatureN[0].value = ccdTemp;
+ IDSetNumber(&TemperatureNP, NULL);
+ break;
+
+ case IPS_ALERT:
+ break;
+ }
+
+ p=p;
+
+ IEAddTimer (POLLMS, ISPoll, NULL);
+}
+
+/* Sets the Image area that the CCD will scan and download.
+ We compensate for binning. */
+int setImageArea(char errmsg[])
+{
+
+ long x_1, y_1, x_2, y_2;
+ long err;
+
+ /* Add the X and Y offsets */
+ x_1 = FrameN[0].value + FLICam->Visible_Area[0];
+ y_1 = FrameN[1].value + FLICam->Visible_Area[1];
+
+ x_2 = x_1 + (FrameN[2].value / BinningN[0].value);
+ y_2 = y_1 + (FrameN[3].value / BinningN[1].value);
+
+ if (x_2 > FLICam->Visible_Area[2])
+ x_2 = FLICam->Visible_Area[2];
+
+ if (y_2 > FLICam->Visible_Area[3])
+ y_2 = FLICam->Visible_Area[3];
+
+ IDLog("The Final image area is (%ld, %ld), (%ld, %ld)\n", x_1, y_1, x_2, y_2);
+
+ FLIImg->width = x_2 - x_1;
+ FLIImg->height = y_2 - y_1;
+
+ if ( (err = FLISetImageArea(fli_dev, x_1, y_1, x_2, y_2) ))
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "FLISetImageArea() failed. %s.\n", strerror((int)-err));
+ IDLog("%s", errmsg);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Downloads the image from the CCD row by row and store them
+ in a raw file.
+ N.B. No processing is done on the image */
+int grabImage()
+{
+ long err;
+ int img_size,i, fd;
+ char errmsg[ERRMSG_SIZE];
+ char filename[] = "/tmp/fitsXXXXXX";
+
+ if ((fd = mkstemp(filename)) < 0)
+ {
+ IDMessage(mydev, "Error making temporary filename.");
+ IDLog("Error making temporary filename.\n");
+ return -1;
+ }
+ close(fd);
+
+ img_size = FLIImg->width * FLIImg->height * sizeof(unsigned short);
+
+ FLIImg->img = malloc (img_size);
+
+ if (FLIImg->img == NULL)
+ {
+ IDMessage(mydev, "Not enough memory to store image.");
+ IDLog("Not enough memory to store image.\n");
+ return -1;
+ }
+
+ for (i=0; i < FLIImg->height ; i++)
+ {
+ if ( (err = FLIGrabRow(fli_dev, &FLIImg->img[i * FLIImg->width], FLIImg->width)))
+ {
+ free(FLIImg->img);
+ IDMessage(mydev, "FLIGrabRow() failed at row %d. %s.", i, strerror((int)-err));
+ IDLog("FLIGrabRow() failed at row %d. %s.\n", i, strerror((int)-err));
+ return -1;
+ }
+ }
+
+ IDMessage(mydev, "Download complete.\n");
+
+ /*err = (ImageFormatS[0].s == ISS_ON) ? writeFITS(FileNameT[0].text, errmsg) : writeRAW(FileNameT[0].text, errmsg);*/
+ err = writeFITS(filename, errmsg);
+
+ if (err)
+ {
+ free(FLIImg->img);
+ IDMessage(mydev, errmsg, NULL);
+ return -1;
+ }
+
+ free(FLIImg->img);
+ return 0;
+
+}
+
+int writeFITS(const char* filename, char errmsg[])
+{
+ FITS_FILE* ofp;
+ int i, j, bpp, bpsl, width, height;
+ long nbytes;
+ FITS_HDU_LIST *hdu;
+
+ ofp = fits_open (filename, "w");
+ if (!ofp)
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "Error: cannot open file for writing.");
+ return (-1);
+ }
+
+ width = FLIImg->width;
+ height = FLIImg->height;
+ bpp = sizeof(unsigned short); /* Bytes per Pixel */
+ bpsl = bpp * FLIImg->width; /* Bytes per Line */
+ nbytes = 0;
+
+ hdu = create_fits_header (ofp, width, height, bpp);
+ if (hdu == NULL)
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "Error: creating FITS header failed.");
+ return (-1);
+ }
+ if (fits_write_header (ofp, hdu) < 0)
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "Error: writing to FITS header failed.");
+ return (-1);
+ }
+
+ /* Convert buffer to BIG endian */
+ for (i=0; i < FLIImg->height; i++)
+ for (j=0 ; j < FLIImg->width; j++)
+ FLIImg->img[FLIImg->width * i + j] = getBigEndian( (FLIImg->img[FLIImg->width * i + j]) );
+
+ for (i= 0; i < FLIImg->height ; i++)
+ {
+ fwrite(FLIImg->img + (i * FLIImg->width), 2, FLIImg->width, ofp->fp);
+ nbytes += bpsl;
+ }
+
+ nbytes = nbytes % FITS_RECORD_SIZE;
+ if (nbytes)
+ {
+ while (nbytes++ < FITS_RECORD_SIZE)
+ putc (0, ofp->fp);
+ }
+
+ if (ferror (ofp->fp))
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "Error: write error occured");
+ return (-1);
+ }
+
+ fits_close (ofp);
+
+ /* Success */
+ ExposeTimeNP.s = IPS_OK;
+ /*IDSetNumber(&ExposeTimeNP, "FITS image written to %s", filename);
+ IDLog("FITS image written to '%s'\n", filename);*/
+ IDSetNumber(&ExposeTimeNP, NULL);
+ IDLog("Loading FITS image...\n");
+
+ uploadFile(filename);
+
+ return 0;
+
+}
+
+void uploadFile(const char* filename)
+{
+ FILE * fitsFile;
+ unsigned char *fitsData, *compressedData;
+ int r=0;
+ unsigned int i =0, nr = 0;
+ uLongf compressedBytes=0;
+ uLong totalBytes;
+ struct stat stat_p;
+
+ if ( -1 == stat (filename, &stat_p))
+ {
+ IDLog(" Error occoured attempting to stat file.\n");
+ return;
+ }
+
+ totalBytes = stat_p.st_size;
+ fitsData = (unsigned char *) malloc (sizeof(unsigned char) * totalBytes);
+ compressedData = (unsigned char *) malloc (sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
+
+ if (fitsData == NULL || compressedData == NULL)
+ {
+ IDLog("Error! low memory. Unable to initialize fits buffers.\n");
+ return;
+ }
+
+ fitsFile = fopen(filename, "r");
+
+ if (fitsFile == NULL)
+ return;
+
+ /* #1 Read file from disk */
+ for (i=0; i < totalBytes; i+= nr)
+ {
+ nr = fread(fitsData + i, 1, totalBytes - i, fitsFile);
+
+ if (nr <= 0)
+ {
+ IDLog("Error reading temporary FITS file.\n");
+ return;
+ }
+ }
+
+ compressedBytes = sizeof(char) * totalBytes + totalBytes / 64 + 16 + 3;
+
+ /* #2 Compress it */
+ r = compress2(compressedData, &compressedBytes, fitsData, totalBytes, 9);
+ if (r != Z_OK)
+ {
+ /* this should NEVER happen */
+ IDLog("internal error - compression failed: %d\n", r);
+ return;
+ }
+
+ /* #3 Send it */
+ imageB.blob = compressedData;
+ imageB.bloblen = compressedBytes;
+ imageB.size = totalBytes;
+ strcpy(imageB.format, ".fits.z");
+ imageBP.s = IPS_OK;
+ IDSetBLOB (&imageBP, NULL);
+
+ free (fitsData);
+ free (compressedData);
+
+}
+
+/* Initiates the exposure procedure */
+void handleExposure(void *p)
+{
+ long err;
+
+ /* no warning */
+ p=p;
+
+ /* BIAS frame is the same as DARK but with minimum period. i.e. readout from camera electronics.
+ */
+ if (FLIImg->frameType == BIAS_FRAME)
+ {
+ if ((err = FLISetExposureTime(fli_dev, 50)))
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ IDSetNumber(&ExposeTimeNP, "FLISetExposureTime() failed. %s.\n", strerror((int)-err));
+ IDLog("FLISetExposureTime() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+ }
+
+ if ((err = FLIExposeFrame(fli_dev)))
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ IDSetNumber(&ExposeTimeNP, "FLIExposeFrame() failed. %s.", strerror((int)-err));
+ IDLog("FLIExposeFrame() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ ExposeTimeNP.s = IPS_BUSY;
+
+ IDSetNumber(&ExposeTimeNP, "Taking a %g seconds frame...", FLIImg->expose / 1000.);
+
+ IDLog("Taking a frame...\n");
+}
+
+/* Retrieves basic data from the CCD upon connection like temperature, array size, firmware..etc */
+void getBasicData()
+{
+
+ char buff[2048];
+ long err;
+
+ IDLog("In getBasicData()\n");
+
+ if ((err = FLIGetModel (fli_dev, buff, 2048)))
+ {
+ IDMessage(mydev, "FLIGetModel() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetModel() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+ else
+ {
+ if ( (FLICam->model = malloc (sizeof(char) * 2048)) == NULL)
+ {
+ IDMessage(mydev, "malloc() failed.");
+ IDLog("malloc() failed.");
+ return;
+ }
+
+ strcpy(FLICam->model, buff);
+ }
+
+ if (( err = FLIGetHWRevision(fli_dev, &FLICam->HWRevision)))
+ {
+ IDMessage(mydev, "FLIGetHWRevision() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetHWRevision() failed. %s.\n", strerror((int)-err));
+
+ return;
+ }
+
+ if (( err = FLIGetFWRevision(fli_dev, &FLICam->FWRevision)))
+ {
+ IDMessage(mydev, "FLIGetFWRevision() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetFWRevision() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ if (( err = FLIGetPixelSize(fli_dev, &FLICam->x_pixel_size, &FLICam->y_pixel_size)))
+ {
+ IDMessage(mydev, "FLIGetPixelSize() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetPixelSize() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ FLICam->x_pixel_size *= 1e6;
+ FLICam->y_pixel_size *= 1e6;
+
+ if (( err = FLIGetArrayArea(fli_dev, &FLICam->Array_Area[0], &FLICam->Array_Area[1], &FLICam->Array_Area[2], &FLICam->Array_Area[3])))
+ {
+ IDMessage(mydev, "FLIGetArrayArea() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetArrayArea() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ if (( err = FLIGetVisibleArea( fli_dev, &FLICam->Visible_Area[0], &FLICam->Visible_Area[1], &FLICam->Visible_Area[2], &FLICam->Visible_Area[3])))
+ {
+ IDMessage(mydev, "FLIGetVisibleArea() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetVisibleArea() failed. %s.\n", strerror((int)-err));
+ }
+
+ if (( err = FLIGetTemperature(fli_dev, &FLICam->temperature)))
+ {
+ IDMessage(mydev, "FLIGetTemperature() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetTemperature() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ IDLog("The CCD Temperature is %f.\n", FLICam->temperature);
+
+ PixelSizeN[0].value = FLICam->x_pixel_size; /* Pixel width (um) */
+ PixelSizeN[1].value = FLICam->y_pixel_size; /* Pixel height (um) */
+ TemperatureN[0].value = FLICam->temperature; /* CCD chip temperatre (degrees C) */
+ FrameN[0].value = 0; /* X */
+ FrameN[1].value = 0; /* Y */
+ FrameN[2].value = FLICam->Visible_Area[2] - FLICam->Visible_Area[0]; /* Frame Width */
+ FrameN[3].value = FLICam->Visible_Area[3] - FLICam->Visible_Area[1]; /* Frame Height */
+
+ FLICam->width = FLIImg->width = FrameN[2].value;
+ FLICam->height = FLIImg->width = FrameN[3].value;
+
+ BinningN[0].value = BinningN[1].value = 1;
+
+ IDLog("The Camera Width is %d ---- %d\n", (int) FLICam->width, (int) FrameN[2].value);
+ IDLog("The Camera Height is %d ---- %d\n", (int) FLICam->height, (int) FrameN[3].value);
+
+ IDSetNumber(&PixelSizeNP, NULL);
+ IDSetNumber(&TemperatureNP, NULL);
+ IDSetNumber(&FrameNP, NULL);
+ IDSetNumber(&BinningNP, NULL);
+
+ IDLog("Exiting getBasicData()\n");
+
+}
+
+int manageDefaults(char errmsg[])
+{
+ long err;
+ int exposeTimeMS;
+
+ exposeTimeMS = (int) (ExposeTimeN[0].value * 1000.);
+
+ IDLog("Setting default exposure time of %d ms.\n", exposeTimeMS);
+ if ( (err = FLISetExposureTime(fli_dev, exposeTimeMS) ))
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "FLISetExposureTime() failed. %s.\n", strerror((int)-err));
+ IDLog(errmsg, NULL);
+ return -1;
+ }
+
+ /* Default frame type is NORMAL */
+ if ( (err = FLISetFrameType(fli_dev, FLI_FRAME_TYPE_NORMAL) ))
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "FLISetFrameType() failed. %s.\n", strerror((int)-err));
+ IDLog(errmsg, NULL);
+ return -1;
+ }
+
+ /* X horizontal binning */
+ if ( (err = FLISetHBin(fli_dev, BinningN[0].value) ))
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "FLISetBin() failed. %s.\n", strerror((int)-err));
+ IDLog(errmsg, NULL);
+ return -1;
+ }
+
+ /* Y vertical binning */
+ if ( (err = FLISetVBin(fli_dev, BinningN[1].value) ))
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "FLISetVBin() failed. %s.\n", strerror((int)-err));
+ IDLog(errmsg, NULL);
+ return -1;
+ }
+
+ IDLog("Setting default binning %f x %f.\n", BinningN[0].value, BinningN[1].value);
+
+ FLISetNFlushes(fli_dev, NFLUSHES);
+
+ /* Set image area */
+ if (setImageArea(errmsg))
+ return -1;
+
+ /* Success */
+ return 0;
+
+}
+
+int getOnSwitch(ISwitchVectorProperty *sp)
+{
+ int i=0;
+ for (i=0; i < sp->nsp ; i++)
+ {
+ /*IDLog("Switch %s is %s\n", sp->sp[i].name, sp->sp[i].s == ISS_ON ? "On" : "Off");*/
+ if (sp->sp[i].s == ISS_ON)
+ return i;
+ }
+
+ return -1;
+}
+
+int checkPowerS(ISwitchVectorProperty *sp)
+{
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(sp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", sp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", sp->label);
+
+ sp->s = IPS_IDLE;
+ IDSetSwitch(sp, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int checkPowerN(INumberVectorProperty *np)
+{
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(np->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", np->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", np->label);
+
+ np->s = IPS_IDLE;
+ IDSetNumber(np, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int checkPowerT(ITextVectorProperty *tp)
+{
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(tp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", tp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", tp->label);
+
+ tp->s = IPS_IDLE;
+ IDSetText(tp, NULL);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+void connectCCD()
+{
+ long err;
+ char errmsg[ERRMSG_SIZE];
+
+ IDLog ("In ConnectCCD\n");
+
+ /* USB by default {USB, SERIAL, PARALLEL, INET} */
+ switch (PowerS[0].s)
+ {
+ case ISS_ON:
+ IDLog("Current portSwitch is %d\n", portSwitchIndex);
+ IDLog("Attempting to find the camera in domain %ld\n", Domains[portSwitchIndex]);
+ if (findcam(Domains[portSwitchIndex])) {
+ PowerSP.s = IPS_IDLE;
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch(&PowerSP, "Error: no cameras were detected.");
+ IDLog("Error: no cameras were detected.\n");
+ return;
+ }
+
+ if ((err = FLIOpen(&fli_dev, FLICam->name, FLIDEVICE_CAMERA | FLICam->domain)))
+ {
+ PowerSP.s = IPS_IDLE;
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch(&PowerSP, "Error: FLIOpen() failed. %s.", strerror( (int) -err));
+ IDLog("Error: FLIOpen() failed. %s.\n", strerror( (int) -err));
+ return;
+ }
+
+ /* Sucess! */
+ PowerS[0].s = ISS_ON;
+ PowerS[1].s = ISS_OFF;
+ PowerSP.s = IPS_OK;
+ IDSetSwitch(&PowerSP, "CCD is online. Retrieving basic data.");
+ IDLog("CCD is online. Retrieving basic data.\n");
+ getBasicData();
+ if (manageDefaults(errmsg))
+ {
+ IDMessage(mydev, errmsg, NULL);
+ IDLog("%s", errmsg);
+ return;
+ }
+
+ break;
+
+ case ISS_OFF:
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_IDLE;
+ if ((err = FLIClose(fli_dev))) {
+ PowerSP.s = IPS_IDLE;
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch(&PowerSP, "Error: FLIClose() failed. %s.", strerror( (int) -err));
+ IDLog("Error: FLIClose() failed. %s.\n", strerror( (int) -err));
+ return;
+ }
+ IDSetSwitch(&PowerSP, "CCD is offline.");
+ break;
+ }
+}
+
+/* isCCDConnected: return 1 if we have a connection, 0 otherwise */
+int isCCDConnected(void)
+{
+ return ((PowerS[0].s == ISS_ON) ? 1 : 0);
+}
+
+int findcam(flidomain_t domain)
+{
+ char **tmplist;
+ long err;
+
+ IDLog("In find Camera, the domain is %ld\n", domain);
+
+ if (( err = FLIList(domain | FLIDEVICE_CAMERA, &tmplist)))
+ {
+ IDLog("FLIList() failed. %s\n", strerror((int)-err));
+ return -1;
+ }
+
+ if (tmplist != NULL && tmplist[0] != NULL)
+ {
+ int i;
+
+ IDLog("Trying to allocate memory to FLICam\n");
+ if ((FLICam = malloc (sizeof (cam_t))) == NULL)
+ {
+ IDLog("malloc() failed.\n");
+ return -1;
+ }
+
+ for (i = 0; tmplist[i] != NULL; i++)
+ {
+ int j;
+
+ for (j = 0; tmplist[i][j] != '\0'; j++)
+ if (tmplist[i][j] == ';')
+ {
+ tmplist[i][j] = '\0';
+ break;
+ }
+ }
+
+ FLICam->domain = domain;
+
+ switch (domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ FLICam->dname = strdup("parallel port");
+ break;
+
+ case FLIDOMAIN_USB:
+ FLICam->dname = strdup("USB");
+ break;
+
+ case FLIDOMAIN_SERIAL:
+ FLICam->dname = strdup("serial");
+ break;
+
+ case FLIDOMAIN_INET:
+ FLICam->dname = strdup("inet");
+ break;
+
+ default:
+ FLICam->dname = strdup("Unknown domain");
+ }
+
+ FLICam->name = strdup(tmplist[0]);
+
+ if ((err = FLIFreeList(tmplist)))
+ {
+ IDLog("FLIFreeList() failed. %s.\n", strerror((int)-err));
+ return -1;
+ }
+
+ } /* end if */
+ else
+ {
+ if ((err = FLIFreeList(tmplist)))
+ {
+ IDLog("FLIFreeList() failed. %s.\n", strerror((int)-err));
+ return -1;
+ }
+
+ return -1;
+ }
+
+ IDLog("Findcam() finished successfully.\n");
+ return 0;
+}
+
+FITS_HDU_LIST * create_fits_header (FITS_FILE *ofp, uint width, uint height, uint bpp)
+{
+ FITS_HDU_LIST *hdulist;
+ char temp_s[80], expose_s[80], binning_s[80], pixel_s[80], frame_s[80];
+ char obsDate[80];
+ char ts[32];
+ struct tm *tp;
+ time_t t;
+
+ time (&t);
+ tp = gmtime (&t);
+ strftime (ts, sizeof(ts), "%Y-%m-%dT%H:%M:%S", tp);
+
+ snprintf(obsDate, 80, "DATE-OBS= '%s' /Observation Date UTC", ts);
+
+ hdulist = fits_add_hdu (ofp);
+ if (hdulist == NULL) return (NULL);
+
+ hdulist->used.simple = 1;
+ hdulist->bitpix = 16;/*sizeof(unsigned short) * 8;*/
+ hdulist->naxis = 2;
+ hdulist->naxisn[0] = width;
+ hdulist->naxisn[1] = height;
+ hdulist->naxisn[2] = bpp;
+ hdulist->used.datamin = 1;
+ hdulist->datamin = min();
+ hdulist->used.datamax = 1;
+ hdulist->datamax = max();
+ hdulist->used.bzero = 1;
+ hdulist->bzero = 0.0;
+ hdulist->used.bscale = 1;
+ hdulist->bscale = 1.0;
+
+ sprintf(temp_s, "CCD-TEMP= %g / degrees celcius", TemperatureN[0].value);
+ sprintf(expose_s, "EXPOSURE= %d / milliseconds", FLIImg->expose);
+ sprintf(binning_s, "BINNING = '(%g x %g)'", BinningN[0].value, BinningN[1].value);
+ sprintf(pixel_s, "PIX-SIZ = '%.0f microns square'", PixelSizeN[0].value);
+ switch (FLIImg->frameType)
+ {
+ case LIGHT_FRAME:
+ strcpy(frame_s, "FRAME = 'Light'");
+ break;
+ case BIAS_FRAME:
+ strcpy(frame_s, "FRAME = 'Bias'");
+ break;
+ case FLAT_FRAME:
+ strcpy(frame_s, "FRAME = 'Flat Field'");
+ break;
+ case DARK_FRAME:
+ strcpy(frame_s, "FRAME = 'Dark'");
+ break;
+ }
+
+ fits_add_card (hdulist, frame_s);
+ fits_add_card (hdulist, temp_s);
+ fits_add_card (hdulist, expose_s);
+ fits_add_card (hdulist, pixel_s);
+ fits_add_card (hdulist, ( char* ) "INSTRUME= 'Finger Lakes Instruments'");
+ fits_add_card (hdulist, obsDate);
+
+ return (hdulist);
+}
+
+double min()
+{
+ double lmin = FLIImg->img[0];
+ int ind=0, i, j;
+
+ for (i= 0; i < FLIImg->height ; i++)
+ for (j= 0; j < FLIImg->width; j++)
+ {
+ ind = (i * FLIImg->width) + j;
+ if (FLIImg->img[ind] < lmin) lmin = FLIImg->img[ind];
+ }
+
+ return lmin;
+}
+
+double max()
+{
+ double lmax = FLIImg->img[0];
+ int ind=0, i, j;
+
+ for (i= 0; i < FLIImg->height ; i++)
+ for (j= 0; j < FLIImg->width; j++)
+ {
+ ind = (i * FLIImg->width) + j;
+ if (FLIImg->img[ind] > lmax) lmax = FLIImg->img[ind];
+ }
+
+ return lmax;
+}
diff --git a/kstars/kstars/indi/fli_wheel.c b/kstars/kstars/indi/fli_wheel.c
new file mode 100644
index 00000000..c991e1e4
--- /dev/null
+++ b/kstars/kstars/indi/fli_wheel.c
@@ -0,0 +1,700 @@
+#if 0
+ FLI WHEEL
+ INDI Interface for Finger Lakes Instruments Filter Wheels
+ Copyright (C) 2005 Gaetano Vocca (yagvoc-web AT yahoo DOT it)
+ Based on fli_ccd by Jasem Mutlaq (mutlaqja AT ikarustech DOT com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "fli/libfli.h"
+#include "fitsrw.h"
+#include "indidevapi.h"
+#include "eventloop.h"
+#include "indicom.h"
+
+void ISInit(void);
+void getBasicData(void);
+void ISPoll(void *);
+void handleExposure(void *);
+void connectFilter(void);
+int findwheel(flidomain_t domain);
+int manageDefaults(char errmsg[]);
+int checkPowerS(ISwitchVectorProperty *sp);
+int checkPowerN(INumberVectorProperty *np);
+int checkPowerT(ITextVectorProperty *tp);
+int getOnSwitch(ISwitchVectorProperty *sp);
+int isFilterConnected(void);
+
+double min(void);
+double max(void);
+
+extern char* me;
+extern int errno;
+
+#define mydev "FLI Wheel"
+
+#define MAIN_GROUP "Main Control"
+
+#define LAST_FILTER 14 /* Max slot index */
+#define FIRST_FILTER 0 /* Min slot index */
+
+#define currentFilter FilterN[0].value
+
+#define POLLMS 1000
+#define LIBVERSIZ 1024
+#define PREFIXSIZ 64
+#define PIPEBUFSIZ 8192
+#define FRAME_ILEN 64
+
+typedef struct {
+ flidomain_t domain;
+ char *dname;
+ char *name;
+ char *model;
+ long HWRevision;
+ long FWRevision;
+ long current_filter;
+ long filter_count;
+ long home;
+} cam_t;
+
+
+static flidev_t fli_dev;
+static cam_t *FLIWheel;
+static int portSwitchIndex;
+static int simulation;
+static int targetFilter;
+
+long int Domains[] = { FLIDOMAIN_USB, FLIDOMAIN_SERIAL, FLIDOMAIN_PARALLEL_PORT, FLIDOMAIN_INET };
+
+/*INDI controls */
+
+/* Connect/Disconnect */
+static ISwitch PowerS[] = {{"CONNECT" , "Connect" , ISS_OFF, 0, 0},{"DISCONNECT", "Disconnect", ISS_ON, 0, 0}};
+static ISwitchVectorProperty PowerSP = { mydev, "CONNECTION" , "Connection", MAIN_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE, PowerS, NARRAY(PowerS), "", 0};
+
+/* Types of Ports */
+static ISwitch PortS[] = {{"USB", "", ISS_ON, 0, 0}, {"Serial", "", ISS_OFF, 0, 0}, {"Parallel", "", ISS_OFF, 0, 0}, {"INet", "", ISS_OFF, 0, 0}};
+static ISwitchVectorProperty PortSP = { mydev, "Port Type", "", MAIN_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, PortS, NARRAY(PortS), "", 0};
+
+/* Filter control */
+static INumber FilterN[] = { {"SLOT", "Active Filter", "%2.0f", FIRST_FILTER, LAST_FILTER, 1, 0, 0, 0, 0}};
+static INumberVectorProperty FilterNP = { mydev, "FILTER_SLOT", "Filter", MAIN_GROUP, IP_RW, 0, IPS_IDLE, FilterN, NARRAY(FilterN), "", 0};
+
+/* send client definitions of all properties */
+void ISInit()
+{
+ static int isInit=0;
+
+ if (isInit)
+ return;
+
+ /* USB by default {USB, SERIAL, PARALLEL, INET} */
+ portSwitchIndex = 0;
+
+ targetFilter = 0;
+
+ /* No Simulation by default */
+ simulation = 0;
+
+ /* Enable the following for simulation mode */
+ /*simulation = 1;
+ IDLog("WARNING: Simulation is on\n");*/
+
+ IEAddTimer (POLLMS, ISPoll, NULL);
+
+ isInit = 1;
+}
+
+void ISGetProperties (const char *dev)
+{
+
+ ISInit();
+
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ /* Main Control */
+ IDDefSwitch(&PowerSP, NULL);
+ IDDefSwitch(&PortSP, NULL);
+ IDDefNumber(&FilterNP, NULL);
+
+}
+
+void ISNewBLOB (const char *dev, const char *name, int sizes[], char *blobs[], char *formats[], char *names[], int n)
+{
+ dev=dev;name=name;sizes=sizes;blobs=blobs;formats=formats;names=names;n=n;
+}
+
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ /* ignore if not ours */
+ if (dev && strcmp (dev, mydev))
+ return;
+
+ ISInit();
+
+ /* Port type */
+ if (!strcmp (name, PortSP.name))
+ {
+ PortSP.s = IPS_IDLE;
+ IUResetSwitches(&PortSP);
+ IUUpdateSwitches(&PortSP, states, names, n);
+ portSwitchIndex = getOnSwitch(&PortSP);
+
+ PortSP.s = IPS_OK;
+ IDSetSwitch(&PortSP, NULL);
+ return;
+ }
+
+ /* Connection */
+ if (!strcmp (name, PowerSP.name))
+ {
+ IUResetSwitches(&PowerSP);
+ IUUpdateSwitches(&PowerSP, states, names, n);
+ connectFilter();
+ return;
+ }
+
+
+}
+
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+ ISInit();
+
+ /* ignore if not ours */
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ /* suppress warning */
+ n=n; dev=dev; name=name; names=names; texts=texts;
+}
+
+
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ long err;
+ INumber *np;
+ long newFilter;
+
+ n = n;
+
+ /* ignore if not ours */
+ if (dev && strcmp (dev, mydev))
+ return;
+
+ ISInit();
+
+
+if (!strcmp(FilterNP.name, name)) {
+ if (simulation) {
+ targetFilter = values[0];
+ FilterNP.s = IPS_BUSY;
+ IDSetNumber(&FilterNP, "Setting current filter to slot %d", targetFilter);
+ IDLog("Setting current filter to slot %d\n", targetFilter);
+ return;
+ }
+
+
+ if (!isFilterConnected()) {
+ IDMessage(mydev, "Device not connected.");
+ FilterNP.s = IPS_IDLE;
+ IDSetNumber(&FilterNP, NULL);
+ return;
+ }
+
+ targetFilter = values[0];
+
+ np = IUFindNumber(&FilterNP, names[0]);
+
+ if (!np)
+ {
+ FilterNP.s = IPS_ALERT;
+ IDSetNumber(&FilterNP, "Unknown error. %s is not a member of %s property.", names[0], name);
+ return;
+ }
+
+ if (targetFilter < FIRST_FILTER || targetFilter > FLIWheel->filter_count - 1)
+ {
+ FilterNP.s = IPS_ALERT;
+ IDSetNumber(&FilterNP, "Error: valid range of filter is from %d to %d", FIRST_FILTER, LAST_FILTER);
+ return;
+ }
+
+ FilterNP.s = IPS_BUSY;
+ IDSetNumber(&FilterNP, "Setting current filter to slot %d", targetFilter);
+ IDLog("Setting current filter to slot %d\n", targetFilter);
+
+ if ( (err = FLISetFilterPos(fli_dev, targetFilter)))
+ {
+ FilterNP.s = IPS_ALERT;
+ IDSetNumber(&FilterNP, "FLISetFilterPos() failed. %s.", strerror((int)-err));
+ IDLog("FLISetFilterPos() failed. %s.", strerror((int)-err));
+ return;
+ }
+
+ /* Check current filter position */
+ if (( err = FLIGetFilterPos(fli_dev, &newFilter))) {
+ FilterNP.s = IPS_ALERT;
+ IDSetNumber(&FilterNP, "FLIGetFilterPos() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetFilterPos() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ if (newFilter == targetFilter) {
+ FLIWheel->current_filter = targetFilter;
+ FilterN[0].value = FLIWheel->current_filter;
+ FilterNP.s = IPS_OK;
+ IDSetNumber(&FilterNP, "Filter set to slot #%d", targetFilter);
+ return;
+ }
+
+ return;
+ }
+}
+
+
+/* Retrieves basic data from the Wheel upon connection like temperature, array size, firmware..etc */
+void getBasicData()
+{
+
+ char buff[2048];
+ long err;
+
+ if ((err = FLIGetModel (fli_dev, buff, 2048)))
+ {
+ IDMessage(mydev, "FLIGetModel() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetModel() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+ else
+ {
+ if ( (FLIWheel->model = malloc (sizeof(char) * 2048)) == NULL)
+ {
+ IDMessage(mydev, "malloc() failed.");
+ IDLog("malloc() failed.");
+ return;
+ }
+
+ strcpy(FLIWheel->model, buff);
+ }
+
+ if (( err = FLIGetHWRevision(fli_dev, &FLIWheel->HWRevision)))
+ {
+ IDMessage(mydev, "FLIGetHWRevision() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetHWRevision() failed. %s.\n", strerror((int)-err));
+
+ return;
+ }
+
+ if (( err = FLIGetFWRevision(fli_dev, &FLIWheel->FWRevision)))
+ {
+ IDMessage(mydev, "FLIGetFWRevision() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetFWRevision() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ if (( err = FLIGetFilterCount(fli_dev, &FLIWheel->filter_count)))
+ {
+ IDMessage(mydev, "FLIGetFilterCount() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetFilterCount() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ IDLog("The filter count is %ld\n", FLIWheel->filter_count);
+
+ FilterN[0].max = FLIWheel->filter_count - 1;
+ FilterNP.s = IPS_OK;
+
+ IUUpdateMinMax(&FilterNP);
+ IDSetNumber(&FilterNP, "Setting basic data");
+
+ IDLog("Exiting getBasicData()\n");
+
+}
+
+int manageDefaults(char errmsg[])
+{
+ long err;
+
+ /*IDLog("Resetting filter wheel to slot %d\n", 0);
+ FLIWheel->home = 0;
+ if (( err = FLISetFilterPos(fli_dev, 0)))
+ {
+ IDMessage(mydev, "FLISetFilterPos() failed. %s.", strerror((int)-err));
+ IDLog("FLISetFilterPos() failed. %s.\n", strerror((int)-err));
+ return (int)-err;
+ }*/
+
+
+ if (( err = FLIGetFilterPos(fli_dev, &FLIWheel->current_filter)))
+ {
+ IDMessage(mydev, "FLIGetFilterPos() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetFilterPos() failed. %s.\n", strerror((int)-err));
+ return (int)-err;
+ }
+
+ IDLog("The current filter is %ld\n", FLIWheel->current_filter);
+
+ FilterN[0].value = FLIWheel->current_filter;
+ IDSetNumber(&FilterNP, "Storing defaults");
+
+ /* Success */
+ return 0;
+
+}
+
+void ISPoll(void *p)
+{
+ static int simMTC = 5;
+
+ if (!isFilterConnected())
+ {
+ IEAddTimer (POLLMS, ISPoll, NULL);
+ return;
+ }
+
+
+ switch (FilterNP.s)
+ {
+ case IPS_IDLE:
+ case IPS_OK:
+ break;
+
+
+ case IPS_BUSY:
+ /* Simulate that it takes 5 seconds to change slot */
+ if (simulation)
+ {
+ simMTC--;
+ if (simMTC == 0)
+ {
+ simMTC = 5;
+ currentFilter = targetFilter;
+ FilterNP.s = IPS_OK;
+ IDSetNumber(&FilterNP, "Filter set to slot #%2.0f", currentFilter);
+ break;
+ }
+ IDSetNumber(&FilterNP, NULL);
+ break;
+ }
+
+
+ /*if (( err = FLIGetFilterPos(fli_dev, &currentFilter)))
+ {
+ FilterNP.s = IPS_ALERT;
+ IDSetNumber(&FilterNP, "FLIGetFilterPos() failed. %s.", strerror((int)-err));
+ IDLog("FLIGetFilterPos() failed. %s.\n", strerror((int)-err));
+ return;
+ }
+
+ if (targetFilter == currentFilter)
+ {
+ FLIWheel->current_filter = currentFilter;
+ FilterNP.s = IPS_OK;
+ IDSetNumber(&FilterNP, "Filter set to slot #%2.0f", currentFilter);
+ return;
+ }
+
+ IDSetNumber(&FilterNP, NULL);*/
+ break;
+
+ case IPS_ALERT:
+ break;
+ }
+
+ IEAddTimer (POLLMS, ISPoll, NULL);
+
+}
+
+
+
+int getOnSwitch(ISwitchVectorProperty *sp)
+{
+ int i=0;
+ for (i=0; i < sp->nsp ; i++)
+ {
+ /*IDLog("Switch %s is %s\n", sp->sp[i].name, sp->sp[i].s == ISS_ON ? "On" : "Off");*/
+ if (sp->sp[i].s == ISS_ON)
+ return i;
+ }
+
+ return -1;
+}
+
+int checkPowerS(ISwitchVectorProperty *sp)
+{
+
+ if (simulation)
+ return 0;
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(sp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the wheel is offline.", sp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the wheel is offline.", sp->label);
+
+ sp->s = IPS_IDLE;
+ IDSetSwitch(sp, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int checkPowerN(INumberVectorProperty *np)
+{
+ if (simulation)
+ return 0;
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(np->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the wheel is offline.", np->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the wheel is offline.", np->label);
+
+ np->s = IPS_IDLE;
+ IDSetNumber(np, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int checkPowerT(ITextVectorProperty *tp)
+{
+ if (simulation)
+ return 0;
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(tp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the wheel is offline.", tp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the wheel is offline.", tp->label);
+
+ tp->s = IPS_IDLE;
+ IDSetText(tp, NULL);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+void connectFilter()
+{
+ long err;
+ char errmsg[ERRMSG_SIZE];
+
+
+ /* USB by default {USB, SERIAL, PARALLEL, INET} */
+ switch (PowerS[0].s)
+ {
+ case ISS_ON:
+
+ if (simulation)
+ {
+ /* Success! */
+ PowerS[0].s = ISS_ON;
+ PowerS[1].s = ISS_OFF;
+ PowerSP.s = IPS_OK;
+ IDSetSwitch(&PowerSP, "Simulation Wheel is online.");
+ IDLog("Simulation Wheel is online.\n");
+ return;
+ }
+
+ IDLog("Current portSwitch is %d\n", portSwitchIndex);
+ IDLog("Attempting to find the device in domain %ld\n", Domains[portSwitchIndex]);
+
+ if (findwheel(Domains[portSwitchIndex]))
+ {
+ PowerSP.s = IPS_IDLE;
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch(&PowerSP, "Error: no wheels were detected.");
+ IDLog("Error: no wheels were detected.\n");
+ return;
+ }
+
+ if ((err = FLIOpen(&fli_dev, FLIWheel->name, FLIWheel->domain | FLIDEVICE_FILTERWHEEL)))
+ {
+ PowerSP.s = IPS_IDLE;
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch(&PowerSP, "Error: FLIOpen() failed. %s.", strerror( (int) -err));
+ IDLog("Error: FLIOpen() failed. %s.\n", strerror( (int) -err));
+ return;
+ }
+
+ /* Success! */
+ PowerS[0].s = ISS_ON;
+ PowerS[1].s = ISS_OFF;
+ PowerSP.s = IPS_OK;
+ IDSetSwitch(&PowerSP, "Wheel is online. Retrieving basic data.");
+ IDLog("Wheel is online. Retrieving basic data.\n");
+ getBasicData();
+
+
+ if (manageDefaults(errmsg))
+ {
+ IDMessage(mydev, errmsg, NULL);
+ IDLog("%s", errmsg);
+ return;
+ }
+
+ break;
+
+ case ISS_OFF:
+
+ if (simulation)
+ {
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_IDLE;
+ IDSetSwitch(&PowerSP, "Wheel is offline.");
+ return;
+ }
+
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_IDLE;
+ if ((err = FLIClose(fli_dev))) {
+ PowerSP.s = IPS_ALERT;
+ IDSetSwitch(&PowerSP, "Error: FLIClose() failed. %s.", strerror( (int) -err));
+ IDLog("Error: FLIClose() failed. %s.\n", strerror( (int) -err));
+ return;
+ }
+ IDSetSwitch(&PowerSP, "Wheel is offline.");
+ break;
+ }
+}
+
+/* isFilterConnected: return 1 if we have a connection, 0 otherwise */
+int isFilterConnected(void)
+{
+ if (simulation)
+ return 1;
+
+ return ((PowerS[0].s == ISS_ON) ? 1 : 0);
+}
+
+int findwheel(flidomain_t domain)
+{
+ char **devlist;
+ long err;
+
+ IDLog("In find Camera, the domain is %ld\n", domain);
+
+ if (( err = FLIList(domain | FLIDEVICE_FILTERWHEEL, &devlist)))
+ {
+ IDLog("FLIList() failed. %s\n", strerror((int)-err));
+ return -1;
+ }
+
+ if (devlist != NULL && devlist[0] != NULL)
+ {
+ int i;
+
+ IDLog("Trying to allocate memory to FLIWheel\n");
+ if ((FLIWheel = malloc (sizeof (cam_t))) == NULL)
+ {
+ IDLog("malloc() failed.\n");
+ return -1;
+ }
+
+ for (i = 0; devlist[i] != NULL; i++)
+ {
+ int j;
+
+ for (j = 0; devlist[i][j] != '\0'; j++)
+ if (devlist[i][j] == ';')
+ {
+ devlist[i][j] = '\0';
+ break;
+ }
+ }
+
+ FLIWheel->domain = domain;
+
+ /* Each driver handles _only_ one camera for now */
+ switch (domain)
+ {
+ case FLIDOMAIN_PARALLEL_PORT:
+ FLIWheel->dname = strdup("parallel port");
+ break;
+
+ case FLIDOMAIN_USB:
+ FLIWheel->dname = strdup("USB");
+ break;
+
+ case FLIDOMAIN_SERIAL:
+ FLIWheel->dname = strdup("serial");
+ break;
+
+ case FLIDOMAIN_INET:
+ FLIWheel->dname = strdup("inet");
+ break;
+
+ default:
+ FLIWheel->dname = strdup("Unknown domain");
+ }
+
+ IDLog("Domain set OK\n");
+
+ FLIWheel->name = strdup(devlist[0]);
+
+ if ((err = FLIFreeList(devlist)))
+ {
+ IDLog("FLIFreeList() failed. %s.\n", strerror((int)-err));
+ return -1;
+ }
+
+ } /* end if */
+ else
+ {
+ if ((err = FLIFreeList(devlist)))
+ {
+ IDLog("FLIFreeList() failed. %s.\n", strerror((int)-err));
+ return -1;
+ }
+
+ return -1;
+ }
+
+ IDLog("Findcam() finished successfully.\n");
+ return 0;
+}
diff --git a/kstars/kstars/indi/fq.c b/kstars/kstars/indi/fq.c
new file mode 100644
index 00000000..ba429d5e
--- /dev/null
+++ b/kstars/kstars/indi/fq.c
@@ -0,0 +1,208 @@
+/* a fifo queue that never fills.
+ * licensed under GNU Lesser Public License version 2.1 or later.
+ * Copyright (C) 2005 Elwood C. Downey ecdowney@clearskyinstitute.com
+ * includes standalone commandline test program, see below.
+ */
+
+/** \file fq.c
+ \brief a fifo queue that never fills.
+
+ Generic FIFO Queue.
+
+ an FQ is a FIFO list of pointers to void, each called an "element".
+ elements are added at q[head]. there are (nq) elements in the list. the
+ element to be removed next is q[head-nq]. there are (head-nq) empty slots
+ at the front of the q array. there are (nmem-head) elements available at
+ the end. if the head reaches the end, existing enties are slid to the front
+ of the array and total memory is adjusted up or down as required.
+
+ example:
+
+ <-------------------- nmem = 17 --------------------------------->
+ <-- head - nq = 6 ---> <-- nq = 4 --> <---- nmem - head = 7 -->
+ ---------------------------------------------------------------------
+ | | | | | | | x | x | x | x | | | | | | | |
+ ---------------------------------------------------------------------
+ 0 1 2 3 4 5 6 7 8 9 ^
+ head = 10
+
+ \author Elwood Downey
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "fq.h"
+
+struct _FQ {
+ void **q; /* malloced array of (void *) */
+ int nq; /* number of elements on queue */
+ int head; /* index into q[] of next empty spot */
+ int nmem; /* number of total slots in q[] */
+ int grow; /* n elements to grow when out of room*/
+};
+
+/* default memory managers, override with setMemFuncsFQ() */
+static void *(*mymalloc)(size_t size) = malloc;
+static void *(*myrealloc)(void *ptr, size_t size) = realloc;
+static void (*myfree)(void *ptr) = free;
+
+static void chkFQ (FQ *q);
+
+/* return pointer to a new FQ, or NULL if no more memory.
+ * grow is an efficiency hint of the number of elements to grow when out of
+ * room, nothing terrible happens if it is wrong.
+ */
+FQ *
+newFQ (int grow)
+{
+ FQ *q = (FQ *)(*mymalloc)(sizeof(FQ));
+ memset (q, 0, sizeof(FQ));
+ q->q = (*mymalloc) (1); /* seed for realloc */
+ q->grow = grow > 0 ? grow : 1;
+ return (q);
+}
+
+/* delete a FQ no longer needed */
+void
+delFQ (FQ *q)
+{
+ (*myfree) (q->q); /* guaranteed set in newFQ() */
+ (*myfree) ((void *)q);
+}
+
+/* push an element onto the given FQ */
+void
+pushFQ (FQ *q, void *e)
+{
+ chkFQ (q);
+ q->q[q->head++] = e;
+ q->nq++;
+}
+
+/* pop and return the next element in the given FQ, or NULL if empty */
+void *
+popFQ (FQ *q)
+{
+ return (q->nq > 0 ? q->q[q->head - q->nq--] : NULL);
+}
+
+/* return next element in the given FQ leaving it on the q, or NULL if empty */
+void *
+peekFQ (FQ *q)
+{
+ return (q->nq > 0 ? q->q[q->head - q->nq] : NULL);
+}
+
+/* return the number of elements in the given FQ */
+int
+nFQ (FQ *q)
+{
+ return (q->nq);
+}
+
+/* install new version of malloc/realloc/free.
+ * N.B. don't call after first use of any other FQ function
+ */
+void
+setMemFuncsFQ (void *(*newmalloc)(size_t size),
+ void *(*newrealloc)(void *ptr, size_t size),
+ void (*newfree)(void *ptr))
+{
+ mymalloc = newmalloc;
+ myrealloc = newrealloc;
+ myfree = newfree;
+}
+
+/* insure q can hold one more element */
+static void
+chkFQ (FQ *q)
+{
+ int infront;
+
+ /* done if still room at end */
+ if (q->nmem > q->head)
+ return;
+
+ /* move list to front */
+ infront = q->head - q->nq;
+ memmove (q->q, &q->q[infront], q->nq * sizeof(void*));
+ q->head -= infront;
+
+ /* realloc to minimum number of grow-sized chunks required */
+ q->nmem = q->grow*(q->head/q->grow+1);
+ q->q = (*myrealloc) (q->q, q->nmem * sizeof(void*));
+}
+
+#if defined(TEST_FQ)
+
+/* to build a stand-alone commandline test program:
+ * cc -DTEST_FQ -o fq fq.c
+ * run ./fq to test push/pop/peek and watch the queue after each operation.
+ * the queue test elements are char, please excuse the ugly casts.
+ */
+
+#include <stdio.h>
+
+/* draw a simple graphical representation of the given FQ */
+static void
+prFQ (FQ *q)
+{
+ int i;
+
+ /* print the q, empty slots print as '.' */
+ for (i = 0; i < q->nmem; i++) {
+ if (i >= q->head - q->nq && i < q->head)
+ printf ("%c", (char)(int)q->q[i]);
+ else
+ printf (".");
+ }
+
+ /* add right-justified stats */
+ printf ("%*s nmem = %2d head = %2d nq = %2d\n", 50-i, "", q->nmem,
+ q->head, q->nq);
+}
+
+int
+main (int ac, char *av[])
+{
+ FQ *q = newFQ(8);
+ int c, e = -1;
+ void *p;
+
+ printf ("Commands:\n");
+ printf (" P = push a letter a-z\n");
+ printf (" p = pop a letter\n");
+ printf (" k = peek into queue\n");
+
+ while ((c = fgetc(stdin)) != EOF) {
+ switch (c) {
+ case 'P':
+ pushFQ (q, (void*)('a'+(e=(e+1)%26)));
+ prFQ(q);
+ break;
+ case 'p':
+ p = popFQ (q);
+ if (p)
+ printf ("popped %c\n", (char)(int)p);
+ else
+ printf ("popped empty q\n");
+ prFQ(q);
+ break;
+ case 'k':
+ p = peekFQ (q);
+ if (p)
+ printf ("peeked %c\n", (char)(int)p);
+ else
+ printf ("peeked empty q\n");
+ prFQ(q);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return (0);
+}
+#endif /* TEST_FQ */
+
diff --git a/kstars/kstars/indi/fq.h b/kstars/kstars/indi/fq.h
new file mode 100644
index 00000000..3d46822b
--- /dev/null
+++ b/kstars/kstars/indi/fq.h
@@ -0,0 +1,17 @@
+/* a fifo queue that never fills.
+ * licensed under GNU Lesser Public License version 2.1 or later.
+ * Copyright (C) 2005 Elwood C. Downey ecdowney@clearskyinstitute.com
+ */
+
+typedef struct _FQ FQ;
+
+extern FQ *newFQ(int grow);
+extern void delFQ (FQ *q);
+extern void pushFQ (FQ *q, void *e);
+extern void *popFQ (FQ *q);
+extern void *peekFQ (FQ *q);
+extern int nFQ (FQ *q);
+extern void setMemFuncsFQ (void *(*newmalloc)(size_t size),
+ void *(*newrealloc)(void *ptr, size_t size),
+ void (*newfree)(void *ptr));
+
diff --git a/kstars/kstars/indi/indi_lpi.cpp b/kstars/kstars/indi/indi_lpi.cpp
new file mode 100644
index 00000000..4a6737fa
--- /dev/null
+++ b/kstars/kstars/indi/indi_lpi.cpp
@@ -0,0 +1,146 @@
+/*
+ Meade LPI Experimental driver
+ Copyright (C) 2005 by Jasem Mutlaq
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include "v4ldriver.h"
+
+class Meade_LPI : public V4L_Driver
+{
+ public:
+ Meade_LPI();
+ ~Meade_LPI();
+
+ #ifdef HAVE_LINUX_VIDEODEV2_H
+ void connectCamera(void);
+ #endif
+
+};
+
+Meade_LPI::Meade_LPI() : V4L_Driver()
+{
+}
+
+Meade_LPI::~Meade_LPI()
+{
+}
+
+#ifdef HAVE_LINUX_VIDEODEV2_H
+void Meade_LPI::connectCamera()
+{
+ char errmsg[ERRMSGSIZ];
+
+ switch (PowerS[0].s)
+ {
+ case ISS_ON:
+ if (v4l_base->connectCam(PortT[0].text, errmsg, V4L2_PIX_FMT_SBGGR8, 352, 288) < 0)
+ {
+ PowerSP.s = IPS_IDLE;
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch(&PowerSP, "Error: unable to open device");
+ IDLog("Error: %s\n", errmsg);
+ return;
+ }
+
+ /* Sucess! */
+ PowerS[0].s = ISS_ON;
+ PowerS[1].s = ISS_OFF;
+ PowerSP.s = IPS_OK;
+ IDSetSwitch(&PowerSP, "Meade LPI is online. Retrieving basic data.");
+
+ v4l_base->registerCallback(newFrame, this);
+
+ V4LFrame->compressedFrame = (unsigned char *) malloc (sizeof(unsigned char) * 1);
+
+ IDLog("Meade LPI is online. Retrieving basic data.\n");
+ getBasicData();
+
+ break;
+
+ case ISS_OFF:
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_IDLE;
+
+ free(V4LFrame->compressedFrame);
+ V4LFrame->compressedFrame = NULL;
+ v4l_base->disconnectCam();
+
+ IDSetSwitch(&PowerSP, "Meade LPI is offline.");
+
+ break;
+ }
+
+}
+#endif
+
+Meade_LPI *MainCam = NULL; /* Main and only camera */
+
+/* send client definitions of all properties */
+void ISInit()
+{
+ if (MainCam == NULL)
+ {
+ MainCam = new Meade_LPI();
+ MainCam->initProperties("Meade LPI");
+ MainCam->initCamBase();
+ }
+}
+
+void ISGetProperties (const char *dev)
+{
+ ISInit();
+
+ MainCam->ISGetProperties(dev);
+}
+
+
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+
+ ISInit();
+
+ MainCam->ISNewSwitch(dev, name, states, names, n);
+}
+
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+
+ ISInit();
+
+ MainCam->ISNewText(dev, name, texts, names, n);
+}
+
+
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+
+ ISInit();
+
+ MainCam->ISNewNumber(dev, name, values, names, n);
+}
+
+void ISNewBLOB (const char */*dev*/, const char */*name*/, int */*sizes[]*/, char **/*blobs[]*/, char **/*formats[]*/, char **/*names[]*/, int /*n*/)
+{
+
+ // We use this if we're receving binary data from the client. Most likely we won't for this driver.
+
+}
+
+
diff --git a/kstars/kstars/indi/indi_philips.cpp b/kstars/kstars/indi/indi_philips.cpp
new file mode 100644
index 00000000..f4106eb6
--- /dev/null
+++ b/kstars/kstars/indi/indi_philips.cpp
@@ -0,0 +1,75 @@
+#if 0
+ V4L INDI Driver
+ INDI Interface for V4L devices (Philips)
+ Copyright (C) 2003-2005 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include "v4lphilips.h"
+
+V4L_Philips *MainCam = NULL; /* Main and only camera */
+
+/* send client definitions of all properties */
+void ISInit()
+{
+ if (MainCam == NULL)
+ {
+ MainCam = new V4L_Philips();
+ MainCam->initProperties("Philips Webcam");
+ MainCam->initCamBase();
+ }
+}
+
+void ISGetProperties (const char *dev)
+{
+ ISInit();
+
+ MainCam->ISGetProperties(dev);
+}
+
+
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+
+ ISInit();
+
+ MainCam->ISNewSwitch(dev, name, states, names, n);
+}
+
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+
+ ISInit();
+
+ MainCam->ISNewText(dev, name, texts, names, n);
+}
+
+
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+
+ ISInit();
+
+ MainCam->ISNewNumber(dev, name, values, names, n);
+}
+
+void ISNewBLOB (const char */*dev*/, const char */*name*/, int */*sizes[]*/, char **/*blobs[]*/, char **/*formats[]*/, char **/*names[]*/, int /*n*/)
+{
+
+ // We use this if we're receving binary data from the client. Most likely we won't for this driver.
+
+}
diff --git a/kstars/kstars/indi/indi_v4l.cpp b/kstars/kstars/indi/indi_v4l.cpp
new file mode 100644
index 00000000..76f1f035
--- /dev/null
+++ b/kstars/kstars/indi/indi_v4l.cpp
@@ -0,0 +1,75 @@
+#if 0
+ V4L INDI Driver
+ INDI Interface for V4L devices
+ Copyright (C) 2003-2005 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include "v4ldriver.h"
+
+V4L_Driver *MainCam = NULL; /* Main and only camera */
+
+/* send client definitions of all properties */
+void ISInit()
+{
+ if (MainCam == NULL)
+ {
+ MainCam = new V4L_Driver();
+ MainCam->initProperties("Video4Linux Generic Device");
+ MainCam->initCamBase();
+ }
+}
+
+void ISGetProperties (const char *dev)
+{
+ ISInit();
+
+ MainCam->ISGetProperties(dev);
+}
+
+
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+
+ ISInit();
+
+ MainCam->ISNewSwitch(dev, name, states, names, n);
+}
+
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+
+ ISInit();
+
+ MainCam->ISNewText(dev, name, texts, names, n);
+}
+
+
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+
+ ISInit();
+
+ MainCam->ISNewNumber(dev, name, values, names, n);
+}
+
+void ISNewBLOB (const char */*dev*/, const char */*name*/, int */*sizes[]*/, char **/*blobs[]*/, char **/*formats[]*/, char **/*names[]*/, int /*n*/)
+{
+
+ // We use this if we're receving binary data from the client. Most likely we won't for this driver.
+
+}
diff --git a/kstars/kstars/indi/indiapi.h b/kstars/kstars/indi/indiapi.h
new file mode 100644
index 00000000..324b7824
--- /dev/null
+++ b/kstars/kstars/indi/indiapi.h
@@ -0,0 +1,363 @@
+#if 0
+ INDI
+ Copyright (C) 2003 Elwood C. Downey
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#ifndef INDI_API_H
+#define INDI_API_H
+
+/** \mainpage Instrument Neutral Distributed Interface INDI
+ \section Introduction
+
+ INDI is a simple XML-like communications protocol described for interactive and automated remote control of diverse instrumentation.\n
+
+ INDI is small, easy to parse, and stateless. In the INDI paradigm each Device poses all command and status functions in terms of settings and getting Properties. Each Property is a vector of one or more names members. Each property has a current value vector; a target value vector; provides information about how it should be sequenced with respect to other Properties to accomplish one coordinated unit of observation; and provides hints as to how it might be displayed for interactive manipulation in a GUI.\n
+
+ Clients learn the Properties of a particular Device at runtime using introspection. This decouples Client and Device implementation histories. Devices have a complete authority over whether to accept commands from Clients. INDI accommpdates intermediate servers, broadcasting, and connection topologies ranging from one-to-one on a single system to many-to-many between systems of different genre.\n
+
+ The INDI protocol can be nested within other XML elements such as constraints for automatic scheduling and execution.\n
+
+ For a complete review on the INDI protocol, please refer to the INDI <a href="http://www.clearskyinstitute.com/INDI/INDI">white paper</a>.
+
+\section Audience Intended Audience
+
+INDI is intended for developers who seek a scalable API for device control and automation. Hardware drivers written under INDI can be used under any INDI-compatible client. INDI serves as a backend only, you need frontend clients to control devices. Current clients include <a href="http://edu.kde.org/kstars">KStars</a>, <a href="http://www.clearyskyinstitute.com/xephem">Xephem</a>, and <a href="http://www.stargazing.net/astropc">Cartes du Ciel</a>.
+
+\section Development Developing under INDI
+
+Please refere to the <a href="http://indi.sf.net/manual/">INDI Developers Manual</a> for a complete guide on INDI's driver developemnt framework.
+
+\section Help
+
+You can find information on INDI development in the <a href="http://indi.sf.net">INDI sourceforge</a> site. Furthermore, you can discuss INDI related issues on the <a href="http://sourceforge.net/mail/?group_id=90275">INDI development mailing list</a>.
+
+\author Elwood Downey
+\author Jasem Mutlaq
+*/
+
+/** \file indiapi.h
+ \brief Constants and Data structure definitions for the interface to the reference INDI C API implementation.
+ \author Elwood C. Downey
+*/
+
+/*******************************************************************************
+ * INDI wire protocol version implemented by this API.
+ * N.B. this is indepedent of the API itself.
+ */
+
+#define INDIV 1.5
+
+/*******************************************************************************
+ * Manifest constants
+ */
+
+/** \typedef ISState
+ \brief Switch state.
+*/
+typedef enum {
+ ISS_OFF, ISS_ON
+} ISState; /* switch state */
+
+/** \typedef IPState
+ \brief Property state.
+*/
+typedef enum {
+ IPS_IDLE, IPS_OK, IPS_BUSY, IPS_ALERT
+} IPState; /* property state */
+
+/** \typedef ISRule
+ \brief Switch vector rule hint.
+*/
+typedef enum {
+ ISR_1OFMANY, ISR_ATMOST1, ISR_NOFMANY
+} ISRule; /* switch vector rule hint */
+
+/** \typedef IPerm
+ \brief Permission hint, with respect to client.
+*/
+typedef enum {
+ IP_RO, IP_WO, IP_RW
+} IPerm; /* permission hint, WRT client */
+
+/* The XML strings for these attributes may be any length but implementations
+ * are only obligued to support these lengths for the various string attributes.
+ */
+#define MAXINDINAME 32
+#define MAXINDILABEL 32
+#define MAXINDIDEVICE 32
+#define MAXINDIGROUP 32
+#define MAXINDIFORMAT 32
+#define MAXINDIBLOBFMT 32
+#define MAXINDITSTAMP 32
+
+/*******************************************************************************
+ * Typedefs for each INDI Property type.
+ *
+ * INumber.format may be any printf-style appropriate for double
+ * or style "m" to create sexigesimal using the form "%<w>.<f>m" where
+ * <w> is the total field width.
+ * <f> is the width of the fraction. valid values are:
+ * 9 -> :mm:ss.ss
+ * 8 -> :mm:ss.s
+ * 6 -> :mm:ss
+ * 5 -> :mm.m
+ * 3 -> :mm
+ *
+ * examples:
+ *
+ * to produce use
+ *
+ * "-123:45" %7.3m
+ * " 0:01:02" %9.6m
+ */
+
+/** \struct IText
+ \brief One text descriptor.
+*/
+typedef struct {
+ /** index name */
+ char name[MAXINDINAME];
+ /** short description */
+ char label[MAXINDILABEL];
+ /** malloced text string */
+ char *text;
+ /** pointer to parent */
+ struct _ITextVectorProperty *tvp;
+ /** handy place to hang helper info */
+ void *aux0;
+ /** handy place to hang helper info */
+ void *aux1;
+} IText;
+
+/** \struct _ITextVectorProperty
+ \brief Text vector property descriptor.
+*/
+typedef struct _ITextVectorProperty {
+ /** device name */
+ char device[MAXINDIDEVICE];
+ /** property name */
+ char name[MAXINDINAME];
+ /** short description */
+ char label[MAXINDILABEL];
+ /** GUI grouping hint */
+ char group[MAXINDIGROUP];
+ /** client accessibility hint */
+ IPerm p;
+ /** current max time to change, secs */
+ double timeout;
+ /** current property state */
+ IPState s;
+ /** texts comprising this vector */
+ IText *tp;
+ /** dimension of tp[] */
+ int ntp;
+ /** ISO 8601 timestamp of this event */
+ char timestamp[MAXINDITSTAMP];
+ /** handy place to hang helper info */
+ void *aux;
+} ITextVectorProperty;
+
+/** \struct INumber
+ \brief One number descriptor.
+*/
+typedef struct {
+ char name[MAXINDINAME]; /** index name */
+ char label[MAXINDILABEL]; /** short description */
+ char format[MAXINDIFORMAT]; /** GUI display format, see above */
+ double min, max; /** range, ignore if min == max */
+ double step; /** step size, ignore if step == 0 */
+ double value; /** current value */
+ struct _INumberVectorProperty *nvp; /** pointer to parent */
+ void *aux0, *aux1; /** handy place to hang helper info */
+} INumber;
+
+/** \struct _INumberVectorProperty
+ \brief Number vector property descriptor.
+
+ INumber.format may be any printf-style appropriate for double or style "m" to create sexigesimal using the form "%\<w\>.\<f\>m" where:\n
+ \<w\> is the total field width.\n
+ \<f\> is the width of the fraction. valid values are:\n
+ 9 -> \<w\>:mm:ss.ss \n
+ 8 -> \<w\>:mm:ss.s \n
+ 6 -> \<w\>:mm:ss \n
+ 5 -> \<w\>:mm.m \n
+ 3 -> \<w\>:mm \n
+
+ examples:\n
+
+ To produce "-123:45", use \%7.3m \n
+ To produce " 0:01:02", use \%9.6m
+*/
+typedef struct _INumberVectorProperty {
+ /** device name */
+ char device[MAXINDIDEVICE];
+ /** property name */
+ char name[MAXINDINAME];
+ /** short description */
+ char label[MAXINDILABEL];
+ /** GUI grouping hint */
+ char group[MAXINDIGROUP];
+ /** client accessibility hint */
+ IPerm p;
+ /** current max time to change, secs */
+ double timeout;
+ /** current property state */
+ IPState s;
+ /** numbers comprising this vector */
+ INumber *np;
+ /** dimension of np[] */
+ int nnp;
+ /** ISO 8601 timestamp of this event */
+ char timestamp[MAXINDITSTAMP];
+ /** handy place to hang helper info */
+ void *aux;
+} INumberVectorProperty;
+
+/** \struct ISwitch
+ \brief One switch descriptor.
+*/
+typedef struct {
+ char name[MAXINDINAME]; /** index name */
+ char label[MAXINDILABEL]; /** this switch's label */
+ ISState s; /** this switch's state */
+ struct _ISwitchVectorProperty *svp; /** pointer to parent */
+ void *aux; /** handy place to hang helper info */
+} ISwitch;
+
+/** \struct _ISwitchVectorProperty
+ \brief Switch vector property descriptor.
+*/
+typedef struct _ISwitchVectorProperty {
+ /** device name */
+ char device[MAXINDIDEVICE];
+ /** property name */
+ char name[MAXINDINAME];
+ /** short description */
+ char label[MAXINDILABEL];
+ /** GUI grouping hint */
+ char group[MAXINDIGROUP];
+ /** client accessibility hint */
+ IPerm p;
+ /** switch behavior hint */
+ ISRule r;
+ /** current max time to change, secs */
+ double timeout;
+ /** current property state */
+ IPState s;
+ /** switches comprising this vector */
+ ISwitch *sp;
+ /** dimension of sp[] */
+ int nsp;
+ /** ISO 8601 timestamp of this event */
+ char timestamp[MAXINDITSTAMP];
+ /** handy place to hang helper info */
+ void *aux;
+} ISwitchVectorProperty;
+
+/** \struct ILight
+ \brief One light descriptor.
+*/
+typedef struct {
+ char name[MAXINDINAME]; /** index name */
+ char label[MAXINDILABEL]; /** this lights's label */
+ IPState s; /** this lights's state */
+ struct _ILightVectorProperty *lvp; /** pointer to parent */
+ void *aux; /** handy place to hang helper info */
+} ILight;
+
+/** \struct _ILightVectorProperty
+ \brief Light vector property descriptor.
+*/
+typedef struct _ILightVectorProperty {
+ /** device name */
+ char device[MAXINDIDEVICE];
+ /** property name */
+ char name[MAXINDINAME];
+ /** short description */
+ char label[MAXINDILABEL];
+ /** GUI grouping hint */
+ char group[MAXINDIGROUP];
+ /** current property state */
+ IPState s;
+ /** lights comprising this vector */
+ ILight *lp;
+ /** dimension of lp[] */
+ int nlp;
+ /** ISO 8601 timestamp of this event */
+ char timestamp[MAXINDITSTAMP];
+ /** handy place to hang helper info */
+ void *aux;
+} ILightVectorProperty;
+
+/** \struct IBLOB
+ \brief One Blob (Binary Large Object) descriptor.
+ */
+typedef struct { /* one BLOB descriptor */
+ /** index name */
+ char name[MAXINDINAME];
+ /** this BLOB's label */
+ char label[MAXINDILABEL];
+ /** format attr */
+ char format[MAXINDIBLOBFMT];
+ /** malloced binary large object bytes */
+ void *blob;
+ /** bytes in blob */
+ int bloblen;
+ /** n uncompressed bytes */
+ int size;
+ /** pointer to parent */
+ struct _IBLOBVectorProperty *bvp;
+ /** handy place to hang helper info */
+ void *aux0, *aux1, *aux2;
+} IBLOB;
+
+/** \struct _IBLOBVectorProperty
+ \brief BLOB (Binary Large Object) vector property descriptor.
+ */
+
+typedef struct _IBLOBVectorProperty { /* BLOB vector property descriptor */
+ /** device name */
+ char device[MAXINDIDEVICE];
+ /** property name */
+ char name[MAXINDINAME];
+ /** short description */
+ char label[MAXINDILABEL];
+ /** GUI grouping hint */
+ char group[MAXINDIGROUP];
+ /** client accessibility hint */
+ IPerm p;
+ /** current max time to change, secs */
+ double timeout;
+ /** current property state */
+ IPState s;
+ /** BLOBs comprising this vector */
+ IBLOB *bp;
+ /** dimension of bp[] */
+ int nbp;
+ /** ISO 8601 timestamp of this event */
+ char timestamp[MAXINDITSTAMP];
+ /** handy place to hang helper info */
+ void *aux;
+} IBLOBVectorProperty;
+
+
+/** \brief Handy macro to find the number of elements in array a[]. Must be used with actual array, not pointer.
+*/
+#define NARRAY(a) (sizeof(a)/sizeof(a[0]))
+
+#endif
diff --git a/kstars/kstars/indi/indicom.c b/kstars/kstars/indi/indicom.c
new file mode 100644
index 00000000..15b02c8e
--- /dev/null
+++ b/kstars/kstars/indi/indicom.c
@@ -0,0 +1,638 @@
+/*
+ INDI LIB
+ Common routines used by all drivers
+ Copyright (C) 2003 by Jason Harris (jharris@30doradus.org)
+ Elwood C. Downey
+
+ This is the C version of the astronomical library in KStars
+ modified by Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+/* needed for sincos() in math.h */
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "indicom.h"
+
+const char * Direction[] = { "North", "West", "East", "South", "All"};
+const char * SolarSystem[] = { "Mercury", "Venus", "Moon", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto"};
+
+/* make it compile on solaris */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338327950288419716939937510582097494459
+#endif
+
+/******** Prototypes ***********/
+double DegToRad( double num );
+double RadToDeg( double num );
+void SinCos( double Degrees, double *sina, double *cosa );
+
+double obliquity(void);
+double constAberr(void);
+double sunMeanAnomaly(void);
+double sunMeanLongitude(void);
+double sunTrueAnomaly(void);
+double sunTrueLongitude(void);
+double earthPerihelionLongitude(void);
+double earthEccentricity(void);
+double dObliq(void);
+double dEcLong(void);
+double julianCenturies(void);
+double p1( int i1, int i2 );
+double p2( int i1, int i2 );
+void updateAstroValues( double jd );
+void nutate(double *RA, double *Dec);
+void aberrate(double *RA, double *Dec);
+void precessFromAnyEpoch(double jd0, double jdf, double *RA, double *Dec);
+void apparentCoord(double jd0, double jdf, double *RA, double *Dec);
+void getSexComponents(double value, int *d, int *m, int *s);
+
+double K = ( 20.49552 / 3600. );
+double Obliquity, K, L, L0, LM, M, M0, O, P;
+double XP, YP, ZP;
+double CX, SX, CY, SY, CZ, SZ;
+double P1[3][3], P2[3][3];
+double deltaObliquity, deltaEcLong;
+double e, T;
+
+double obliquity() { return Obliquity; }
+double constAberr() { return K; }
+double sunMeanAnomaly() { return M; }
+double sunMeanLongitude() { return L; }
+double sunTrueAnomaly() { return M0; }
+double sunTrueLongitude() { return L0; }
+double earthPerihelionLongitude() { return P; }
+double earthEccentricity() { return e; }
+double dObliq() { return deltaObliquity; }
+double dEcLong() { return deltaEcLong; }
+double julianCenturies() { return T; }
+double p1( int i1, int i2 ) { return P1[i1][i2]; }
+double p2( int i1, int i2 ) { return P2[i1][i2]; }
+
+void updateAstroValues( double jd )
+{
+ static double days = 0;
+ double jm;
+ double C, U, dObliq2;
+ /* Nutation parameters */
+ double L2, M2, O2;
+ double sin2L, cos2L, sin2M, cos2M;
+ double sinO, cosO, sin2O, cos2O;
+
+ /* no need to recalculate if same as previous JD */
+ if (days == jd)
+ return;
+
+ days = jd;
+
+ /* Julian Centuries since J2000.0 */
+ T = ( jd - J2000 ) / 36525.;
+
+ /* Julian Millenia since J2000.0 */
+ jm = T / 10.0;
+
+ /* Sun's Mean Longitude */
+ L = ( 280.46645 + 36000.76983*T + 0.0003032*T*T );
+
+ /* Sun's Mean Anomaly */
+ M = ( 357.52910 + 35999.05030*T - 0.0001559*T*T - 0.00000048*T*T*T );
+
+ /* Moon's Mean Longitude */
+ LM = ( 218.3164591 + 481267.88134236*T - 0.0013268*T*T + T*T*T/538841. - T*T*T*T/6519400.);
+
+ /* Longitude of Moon's Ascending Node */
+ O = ( 125.04452 - 1934.136261*T + 0.0020708*T*T + T*T*T/450000.0 );
+
+ /* Earth's orbital eccentricity */
+ e = 0.016708617 - 0.000042037*T - 0.0000001236*T*T;
+
+ C = ( 1.914600 - 0.004817*T - 0.000014*T*T ) * sin( DegToRad(M) )
+ + ( 0.019993 - 0.000101*T ) * sin( 2.0* DegToRad(M) )
+ + 0.000290 * sin( 3.0* DegToRad(M));
+
+ /* Sun's True Longitude */
+ L0 = ( L + C );
+
+ /* Sun's True Anomaly */
+ M0 = ( M + C );
+
+ /* Obliquity of the Ecliptic */
+ U = T/100.0;
+ dObliq2 = -4680.93*U - 1.55*U*U + 1999.25*U*U*U
+ - 51.38*U*U*U*U - 249.67*U*U*U*U*U
+ - 39.05*U*U*U*U*U*U + 7.12*U*U*U*U*U*U*U
+ + 27.87*U*U*U*U*U*U*U*U + 5.79*U*U*U*U*U*U*U*U*U
+ + 2.45*U*U*U*U*U*U*U*U*U*U;
+ Obliquity = ( 23.43929111 + dObliq2/3600.0);
+
+ O2 = ( 2.0 * O );
+ L2 = ( 2.0 * L ); /* twice mean ecl. long. of Sun */
+ M2 = ( 2.0 * LM); /* twice mean ecl. long. of Moon */
+
+ SinCos( O, &sinO, &cosO );
+ SinCos( O2, &sin2O, &cos2O );
+ SinCos( L2, &sin2L, &cos2L );
+ SinCos( M2, &sin2M, &cos2M );
+
+ deltaEcLong = ( -17.2*sinO - 1.32*sin2L - 0.23*sin2M + 0.21*sin2O)/3600.0; /* Ecl. long. correction */
+ deltaObliquity = ( 9.2*cosO + 0.57*cos2L + 0.10*cos2M - 0.09*cos2O)/3600.0; /* Obliq. correction */
+
+ /* Compute Precession Matrices: */
+ XP = ( 0.6406161*T + 0.0000839*T*T + 0.0000050*T*T*T );
+ YP = ( 0.5567530*T - 0.0001185*T*T - 0.0000116*T*T*T );
+ ZP = ( 0.6406161*T + 0.0003041*T*T + 0.0000051*T*T*T );
+
+ SinCos(XP, &SX, &CX );
+ SinCos(YP, &SY, &CY );
+ SinCos(ZP, &SZ, &CZ );
+
+ /* P1 is used to precess from any epoch to J2000 */
+ P1[0][0] = CX*CY*CZ - SX*SZ;
+ P1[1][0] = CX*CY*SZ + SX*CZ;
+ P1[2][0] = CX*SY;
+ P1[0][1] = -1.0*SX*CY*CZ - CX*SZ;
+ P1[1][1] = -1.0*SX*CY*SZ + CX*CZ;
+ P1[2][1] = -1.0*SX*SY;
+ P1[0][2] = -1.0*SY*CZ;
+ P1[1][2] = -1.0*SY*SZ;
+ P1[2][2] = CY;
+
+ /* P2 is used to precess from J2000 to any other epoch (it is the transpose of P1) */
+ P2[0][0] = CX*CY*CZ - SX*SZ;
+ P2[1][0] = -1.0*SX*CY*CZ - CX*SZ;
+ P2[2][0] = -1.0*SY*CZ;
+ P2[0][1] = CX*CY*SZ + SX*CZ;
+ P2[1][1] = -1.0*SX*CY*SZ + CX*CZ;
+ P2[2][1] = -1.0*SY*SZ;
+ P2[0][2] = CX*SY;
+ P2[1][2] = -1.0*SX*SY;
+ P2[2][2] = CY;
+
+}
+
+double DegToRad( double num )
+{
+ /*return (num * deg_rad);*/
+ return (num * (M_PI / 180.0));
+}
+
+double RadToDeg( double num )
+{
+ return (num / (M_PI / 180.0));
+}
+
+void SinCos( double Degrees, double *sina, double *cosa )
+{
+ /**We have two versions of this function. One is ANSI standard, but
+ *slower. The other is faster, but is GNU only.
+ *Using the __GLIBC_ and __GLIBC_MINOR_ constants to determine if the
+ * GNU extension sincos() is defined.
+ */
+ static int rDirty = 1;
+ double Sin, Cos;
+
+
+ if (rDirty)
+ {
+ #ifdef __GLIBC__
+ #if ( __GLIBC__ >= 2 && __GLIBC_MINOR__ >=1 && !defined(__UCLIBC__))
+ /* GNU version */
+ sincos( DegToRad(Degrees), &Sin, &Cos );
+ #else
+ /* For older GLIBC versions */
+ Sin = ::sin( DegToRad(Degrees) );
+ Cos = ::cos( DegToRad(Degrees) );
+ #endif
+ #else
+ /* ANSI-compliant version */
+ Sin = sin( DegToRad(Degrees) );
+ Cos = cos( DegToRad(Degrees) );
+ rDirty = 0;
+ #endif
+ }
+ else
+ {
+ Sin = sin( DegToRad(Degrees) );
+ Cos = cos( DegToRad(Degrees) );
+ }
+
+ *sina = Sin;
+ *cosa = Cos;
+}
+
+double calculateDec(double latitude, double SDTime)
+{
+ if (SDTime > 12) SDTime -= 12;
+
+ return RadToDeg ( atan ( (cos (DegToRad (latitude)) / sin (DegToRad (latitude))) * cos (DegToRad (SDTime))) );
+
+}
+
+double calculateRA(double SDTime)
+{
+ double ra;
+
+ ra = SDTime + 12;
+
+ if (ra < 24)
+ return ra;
+ else
+ return (ra - 24);
+}
+
+
+void nutate(double *RA, double *Dec)
+{
+ double cosRA, sinRA, cosDec, sinDec, tanDec;
+ double dRA1, dDec1;
+ double cosOb, sinOb;
+
+ SinCos( *RA, &sinRA, &cosRA );
+ SinCos( *Dec, &sinDec, &cosDec );
+
+ SinCos( obliquity(), &sinOb, &cosOb );
+
+ /* Step 2: Nutation */
+ /* approximate method */
+ tanDec = sinDec/cosDec;
+
+ dRA1 = ( dEcLong()*( cosOb + sinOb*sinRA*tanDec ) - dObliq()*cosRA*tanDec );
+ dDec1 = ( dEcLong()*( sinOb*cosRA ) + dObliq()*sinRA );
+
+ *RA = ( *RA + dRA1 );
+ *Dec = ( *Dec+ dDec1);
+}
+
+void aberrate(double *RA, double *Dec)
+{
+ double cosRA, sinRA, cosDec, sinDec;
+ double dRA2, dDec2;
+ double cosOb, sinOb, cosL, sinL, cosP, sinP;
+ double K2, e2, tanOb;
+
+ K2 = constAberr(); /* constant of aberration */
+ e2 = earthEccentricity();
+
+ SinCos( *RA, &sinRA, &cosRA );
+ SinCos( *Dec, &sinDec, &cosDec );
+
+ SinCos( obliquity(), &sinOb, &cosOb );
+ tanOb = sinOb/cosOb;
+
+ SinCos( sunTrueLongitude(), &sinL, &cosL );
+ SinCos( earthPerihelionLongitude(), &sinP, &cosP );
+
+ /* Step 3: Aberration */
+ dRA2 = ( -1.0 * K2 * ( cosRA * cosL * cosOb + sinRA * sinL )/cosDec
+ + e2 * K2 * ( cosRA * cosP * cosOb + sinRA * sinP )/cosDec );
+
+ dDec2 = ( -1.0 * K2 * ( cosL * cosOb * ( tanOb * cosDec - sinRA * sinDec ) + cosRA * sinDec * sinL )
+ + e2 * K2 * ( cosP * cosOb * ( tanOb * cosDec - sinRA * sinDec ) + cosRA * sinDec * sinP ) );
+
+ *RA = ( *RA + dRA2 );
+ *Dec = ( *Dec + dDec2);
+}
+
+void precessFromAnyEpoch(double jd0, double jdf, double *RA, double *Dec)
+{
+ double cosRA0, sinRA0, cosDec0, sinDec0;
+ double v[3], s[3];
+ unsigned int i=0;
+
+ SinCos( *RA, &sinRA0, &cosRA0 );
+ SinCos( *Dec, &sinDec0, &cosDec0 );
+
+ /* Need first to precess to J2000.0 coords */
+
+ if ( jd0 != J2000 )
+ {
+
+ /* v is a column vector representing input coordinates. */
+
+ updateAstroValues(jd0);
+
+ v[0] = cosRA0*cosDec0;
+ v[1] = sinRA0*cosDec0;
+ v[2] = sinDec0;
+
+
+ /*s is the product of P1 and v; s represents the
+ coordinates precessed to J2000 */
+ for ( i=0; i<3; ++i ) {
+ s[i] = p1( 0, i )*v[0] + p1( 1, i )*v[1] +
+ p1( 2, i )*v[2];
+ }
+
+ } else
+ {
+
+ /* Input coords already in J2000, set s accordingly. */
+ s[0] = cosRA0*cosDec0;
+ s[1] = sinRA0*cosDec0;
+ s[2] = sinDec0;
+ }
+
+ updateAstroValues(jdf);
+
+ /* Multiply P2 and s to get v, the vector representing the new coords. */
+
+ for ( i=0; i<3; ++i ) {
+ v[i] = p2( 0, i )*s[0] + p2( 1, i )*s[1] +
+ p2( 2, i )*s[2];
+ }
+
+ /*Extract RA, Dec from the vector:
+ RA.setRadians( atan( v[1]/v[0] ) ); */
+
+ *RA = RadToDeg( atan2( v[1],v[0] ) );
+ *Dec = RadToDeg( asin( v[2] ) );
+
+ if (*RA < 0.0 )
+ *RA = ( *RA + 360.0 );
+}
+
+void apparentCoord(double jd0, double jdf, double *RA, double *Dec)
+{
+ *RA = *RA * 15.0;
+
+ precessFromAnyEpoch(jd0,jdf, RA, Dec);
+
+ updateAstroValues(jdf);
+
+ nutate(RA, Dec);
+ aberrate(RA, Dec);
+
+ *RA = *RA / 15.0;
+}
+
+double UTtoJD(struct tm *utm)
+{
+ int year, month, day, hour, minute, second;
+ int m, y, A, B, C, D;
+ double d, jd;
+
+ /* Note: The tm_year was modified by adding +1900 to it since tm_year refers
+ to the number of years after 1900. The month field was also modified by adding 1 to it
+ since the tm_mon range is from 0 to 11 */
+ year = utm->tm_year + 1900;
+ month = utm->tm_mon + 1;
+ day = utm->tm_mday;
+ hour = utm->tm_hour;
+ minute = utm->tm_min;
+ second = utm->tm_sec;
+
+
+ if (month > 2)
+ {
+ m = month;
+ y = year;
+ } else
+ {
+ y = year - 1;
+ m = month + 12;
+ }
+
+ /* If the date is after 10/15/1582, then take Pope Gregory's modification
+ to the Julian calendar into account */
+
+ if (( year >1582 ) ||
+ ( year ==1582 && month >9 ) ||
+ ( year ==1582 && month ==9 && day >15 ))
+ {
+ A = (int) y/100;
+ B = 2 - A + (int) A/4;
+ } else {
+ B = 0;
+ }
+
+ if (y < 0) {
+ C = (int) ((365.25*y) - 0.75);
+ } else {
+ C = (int) (365.25*y);
+ }
+
+ D = (int) (30.6001*(m+1));
+
+ d = (double) day + ( (double) hour + ( (double) minute + (double) second/60.0)/60.0)/24.0;
+ jd = B + C + D + d + 1720994.5;
+
+ return jd;
+}
+
+double JDtoGMST( double jd )
+{
+ double Gmst;
+
+ /* Julian Centuries since J2000.0 */
+ T = ( jd - J2000 ) / 36525.;
+
+ /* Greewich Mean Sidereal Time */
+
+ Gmst = 280.46061837
+ + 360.98564736629*(jd-J2000)
+ + 0.000387933*T*T
+ - T*T*T/38710000.0;
+
+ return Gmst;
+}
+
+int extractISOTime(char *timestr, struct tm *utm)
+{
+
+ if (strptime(timestr, "%Y-%m-%dT%H:%M:%S", utm))
+ return (0);
+ if (strptime(timestr, "%Y/%m/%dT%H:%M:%S", utm))
+ return (0);
+ if (strptime(timestr, "%Y:%m:%dT%H:%M:%S", utm))
+ return (0);
+ if (strptime(timestr, "%Y-%m-%dT%H-%M-%S", utm))
+ return (0);
+
+ return (-1);
+
+}
+
+/* sprint the variable a in sexagesimal format into out[].
+ * w is the number of spaces for the whole part.
+ * fracbase is the number of pieces a whole is to broken into; valid options:
+ * 360000: <w>:mm:ss.ss
+ * 36000: <w>:mm:ss.s
+ * 3600: <w>:mm:ss
+ * 600: <w>:mm.m
+ * 60: <w>:mm
+ * return number of characters written to out, not counting final '\0'.
+ */
+int
+fs_sexa (char *out, double a, int w, int fracbase)
+{
+ char *out0 = out;
+ unsigned long n;
+ int d;
+ int f;
+ int m;
+ int s;
+ int isneg;
+
+ /* save whether it's negative but do all the rest with a positive */
+ isneg = (a < 0);
+ if (isneg)
+ a = -a;
+
+ /* convert to an integral number of whole portions */
+ n = (unsigned long)(a * fracbase + 0.5);
+ d = n/fracbase;
+ f = n%fracbase;
+
+ /* form the whole part; "negative 0" is a special case */
+ if (isneg && d == 0)
+ out += sprintf (out, "%*s-0", w-2, "");
+ else
+ out += sprintf (out, "%*d", w, isneg ? -d : d);
+
+ /* do the rest */
+ switch (fracbase) {
+ case 60: /* dd:mm */
+ m = f/(fracbase/60);
+ out += sprintf (out, ":%02d", m);
+ break;
+ case 600: /* dd:mm.m */
+ out += sprintf (out, ":%02d.%1d", f/10, f%10);
+ break;
+ case 3600: /* dd:mm:ss */
+ m = f/(fracbase/60);
+ s = f%(fracbase/60);
+ out += sprintf (out, ":%02d:%02d", m, s);
+ break;
+ case 36000: /* dd:mm:ss.s*/
+ m = f/(fracbase/60);
+ s = f%(fracbase/60);
+ out += sprintf (out, ":%02d:%02d.%1d", m, s/10, s%10);
+ break;
+ case 360000: /* dd:mm:ss.ss */
+ m = f/(fracbase/60);
+ s = f%(fracbase/60);
+ out += sprintf (out, ":%02d:%02d.%02d", m, s/100, s%100);
+ break;
+ default:
+ printf ("fs_sexa: unknown fracbase: %d\n", fracbase);
+ exit(1);
+ }
+
+ return (out - out0);
+}
+
+/* convert sexagesimal string str AxBxC to double.
+ * x can be anything non-numeric. Any missing A, B or C will be assumed 0.
+ * optional - and + can be anywhere.
+ * return 0 if ok, -1 if can't find a thing.
+ */
+int
+f_scansexa (
+const char *str0, /* input string */
+double *dp) /* cracked value, if return 0 */
+{
+ double a = 0, b = 0, c = 0;
+ char str[128];
+ char *neg;
+ int r;
+
+ /* copy str0 so we can play with it */
+ strncpy (str, str0, sizeof(str)-1);
+ str[sizeof(str)-1] = '\0';
+
+ neg = strchr(str, '-');
+ if (neg)
+ *neg = ' ';
+ r = sscanf (str, "%lf%*[^0-9]%lf%*[^0-9]%lf", &a, &b, &c);
+ if (r < 1)
+ return (-1);
+ *dp = a + b/60 + c/3600;
+ if (neg)
+ *dp *= -1;
+ return (0);
+}
+
+void getSexComponents(double value, int *d, int *m, int *s)
+{
+
+ *d = (int) fabs(value);
+ *m = (int) ((fabs(value) - *d) * 60.0);
+ *s = (int) rint(((fabs(value) - *d) * 60.0 - *m) *60.0);
+
+ if (value < 0)
+ *d *= -1;
+}
+
+/* fill buf with properly formatted INumber string. return length */
+int
+numberFormat (char *buf, const char *format, double value)
+{
+ int w, f, s;
+ char m;
+
+ if (sscanf (format, "%%%d.%d%c", &w, &f, &m) == 3 && m == 'm') {
+ /* INDI sexi format */
+ switch (f) {
+ case 9: s = 360000; break;
+ case 8: s = 36000; break;
+ case 6: s = 3600; break;
+ case 5: s = 600; break;
+ default: s = 60; break;
+ }
+ return (fs_sexa (buf, value, w-f, s));
+ } else {
+ /* normal printf format */
+ return (sprintf (buf, format, value));
+ }
+}
+
+double angularDistance(double fromRA, double fromDEC, double toRA, double toDEC)
+{
+
+ double dalpha = DegToRad(fromRA) - DegToRad(toRA);
+ double ddelta = DegToRad(fromDEC) - DegToRad(toDEC);
+
+ double sa = sin(dalpha/2.);
+ double sd = sin(ddelta/2.);
+
+ double hava = sa*sa;
+ double havd = sd*sd;
+
+ double aux = havd + cos (DegToRad(fromDEC)) * cos(DegToRad(toDEC)) * hava;
+
+ return (RadToDeg ( 2 * fabs(asin( sqrt(aux) ))));
+}
+
+/* return current system time in message format */
+const char *
+timestamp()
+{
+ static char ts[32];
+ struct tm *tp;
+ time_t t;
+
+ time (&t);
+ tp = gmtime (&t);
+ strftime (ts, sizeof(ts), "%Y-%m-%dT%H:%M:%S", tp);
+ return (ts);
+}
+
diff --git a/kstars/kstars/indi/indicom.h b/kstars/kstars/indi/indicom.h
new file mode 100644
index 00000000..726c7dcd
--- /dev/null
+++ b/kstars/kstars/indi/indicom.h
@@ -0,0 +1,272 @@
+/*
+ INDI LIB
+ Common routines used by all drivers
+ Copyright (C) 2003 by Jason Harris (jharris@30doradus.org)
+ Elwood C. Downey
+
+ This is the C version of the astronomical library in KStars
+ modified by Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+/** \file indicom.h
+ \brief Implementations for common astronomical routines.
+
+ \author Jason Harris
+ \author Elwood C. Downey
+ \author Jasem Mutlaq
+*/
+
+#ifndef INDICOM_H
+#define INDICOM_H
+
+#include <time.h>
+
+#define J2000 2451545.0
+#define TRACKING_THRESHOLD 0.05 /* 3' for tracking */
+#define ERRMSG_SIZE 1024
+
+extern const char * Direction[];
+extern const char * SolarSystem[];
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup mathFunctions Handy math routines.
+ */
+/*@{*/
+
+/** \brief Convert degrees to radians.
+ \param num number in degrees.
+ \return number in radians.
+*/
+double DegToRad( double num );
+
+/** \brief Convert radians to degrees.
+ \param num number in radians.
+ \return number in degrees.
+*/
+double RadToDeg( double num );
+
+/** \brief Get the sin and cosine of a number.
+
+ The function attempts to use GNU sincos extension when possible. The sin and cosine values for \e Degrees are stored in the \e sina and \e cosa parameters.
+ \param Degrees the number in degrees to return its sin and cosine.
+ \param sina pointer to a double to hold the sin value.
+ \param cosa pointer to a double to hold the cosine value.
+*/
+void SinCos( double Degrees, double *sina, double *cosa );
+
+/*@}*/
+
+/**
+ * \defgroup ephemerisFunctions Common ephemeris functions.
+
+ The ephemeris functions are date-dependent. Call updateAstroValues() to update orbital values used in many algorithms before using any ephemeris function. You only need to call updateAstroValues() again if you need to update the orbital values for a different date.
+ */
+/*@{*/
+
+/** \brief Returns the obliquity of orbit.
+*/
+double obliquity();
+
+/** \brief Returns the constant of aberration (20.49 arcsec). */
+double constAberr();
+
+/** \brief Returns the mean solar anomaly. */
+double sunMeanAnomaly();
+
+/** \brief Returns the mean solar longitude. */
+double sunMeanLongitude();
+
+/** \brief Returns the true solar anomaly. */
+double sunTrueAnomaly();
+
+/** \brief Returns the true solar longitude. */
+double sunTrueLongitude();
+
+/** \brief Returns the longitude of the Earth's perihelion point. */
+double earthPerihelionLongitude();
+
+/** \brief Returns eccentricity of Earth's orbit.*/
+double earthEccentricity();
+
+/** \brief Returns the change in obliquity due to the nutation of Earth's orbit. */
+double dObliq();
+
+/** \brief Returns the change in Ecliptic Longitude due to nutation. */
+double dEcLong();
+
+/** \brief Returns Julian centuries since J2000*/
+double julianCenturies();
+
+/** \brief Returns element of P1 precession array at position [i1][i2] */
+double p1( int i1, int i2 );
+
+/** \brief Returns element of P2 precession array at position [i1][i2] */
+double p2( int i1, int i2 );
+
+/** \brief Update all orbital values for the given date as an argument. Any subsecquent functions will use values affected by this date until changed.
+ \param jd Julian date
+ */
+void updateAstroValues( double jd );
+
+/** \brief Calculates the declination on the celestial sphere at 0 degrees altitude given the siderial time and latitude.
+ \param latitude Current latitude.
+ \param SDTime Current sideral time.
+ \return Returns declinatation at 0 degrees altitude for the given parameters.
+ */
+double calculateDec(double latitude, double SDTime);
+
+/** \brief Calculates the right ascension on the celestial sphere at 0 degrees azimuth given the siderial time.
+ \param SDTime Current sidereal time.
+ \return Returns right ascension at 0 degrees azimith for the given parameters.
+ */
+double calculateRA(double SDTime);
+
+/** \brief Calculates the angular distance between two points on the celestial sphere.
+ \param fromRA Right ascension of starting point in degrees.
+ \param fromDEC Declination of starting point in degrees.
+ \param toRA Right ascension of ending point in degrees.
+ \param toDEC Declination of ending point in degrees.
+ \return Angular seperation in degrees.
+*/
+double angularDistance(double fromRA, double fromDEC, double toRA, double toDEC);
+
+/** \brief Nutate a given RA and Dec.
+ \param RA a pointer to a double containing the Right ascension in degrees to nutate. The function stores the processed Right ascension back in this variable.
+ \param Dec a pointer to a double containing the delination in degrees to nutate. The function stores the processed delination back in this variable.
+*/
+void nutate(double *RA, double *Dec);
+
+/** \brief Aberrate a given RA and Dec.
+ \param RA a pointer to a double containing the Right ascension in degrees to aberrate. The function stores the processed Right ascension back in this variable.
+ \param Dec a pointer to a double containing the delination in degrees to aberrate. The function stores the processed delination back in this variable.
+*/
+void aberrate(double *RA, double *Dec);
+
+/** \brief Precess the given RA and Dec from any epoch to any epoch.
+ \param jd0 starting epoch.
+ \param jdf final epoch.
+ \param RA a pointer to a double containing the Right ascension in degrees to precess. The function stores the processed Right ascension back in this variable.
+ \param Dec a pointer to a double containing the delination in degrees to precess. The function stores the processed delination back in this variable.
+*/
+void precessFromAnyEpoch(double jd0, double jdf, double *RA, double *Dec);
+
+/** \brief Calculate the apparent coordiantes for RA and Dec from any epoch to any epoch.
+ \param jd0 starting epoch.
+ \param jdf final epoch.
+ \param RA a pointer to a double containing the Right ascension in hours. The function stores the processed Right ascension back in this variable.
+ \param Dec a pointer to a double containing the delination in degrees. The function stores the processed delination back in this variable.
+*/
+void apparentCoord(double jd0, double jdf, double *RA, double *Dec);
+
+/*@}*/
+
+
+/**
+ * \defgroup convertFunctions Handy formatting and conversion routines.
+ */
+/*@{*/
+
+/** \brief Converts a sexagesimal number to a string.
+
+ sprint the variable a in sexagesimal format into out[].
+
+ \param out a pointer to store the sexagesimal number.
+ \param a the sexagesimal number to convert.
+ \param w the number of spaces in the whole part.
+ \param fracbase is the number of pieces a whole is to broken into; valid options:\n
+ \li 360000: \<w\>:mm:ss.ss
+ \li 36000: \<w\>:mm:ss.s
+ \li 3600: \<w\>:mm:ss
+ \li 600: \<w\>:mm.m
+ \li 60: \<w\>:mm
+
+ \return number of characters written to out, not counting final null terminator.
+ */
+int fs_sexa (char *out, double a, int w, int fracbase);
+
+/** \brief convert sexagesimal string str AxBxC to double.
+
+ x can be anything non-numeric. Any missing A, B or C will be assumed 0. Optional - and + can be anywhere.
+
+ \param str0 string containing sexagesimal number.
+ \param dp pointer to a double to store the sexagesimal number.
+ \return return 0 if ok, -1 if can't find a thing.
+ */
+int f_scansexa (const char *str0, double *dp);
+
+/** \brief Extract ISO 8601 time and store it in a tm struct.
+ \param timestr a string containing date and time in ISO 8601 format.
+ \param utm a pointer to a \e tm structure to store the extracted time and date.
+ \return 0 on success, -1 on failure.
+*/
+int extractISOTime(char *timestr, struct tm *utm);
+
+/** \brief Converts Universal Time to Julian Date.
+ \param utm a pointer to a structure holding the universal time and date.
+ \return The Julian date fot the passed universal time.
+*/
+double UTtoJD(struct tm *utm);
+
+/** \brief Return the degree, minute, and second components of a sexagesimal number.
+ \param value sexagesimal number to decompose.
+ \param d a pointer to double to store the degrees field.
+ \param m a pointer to a double to store the minutes field.
+ \param s a pointer to a double to store the seconds field.
+*/
+
+/** \brief Converts Julian Date to Greenwich Sidereal Time.
+ \param jd The Julian date
+ \return GMST in degrees
+*/
+double JDtoGMST( double jd );
+
+void getSexComponents(double value, int *d, int *m, int *s);
+
+/** \brief Fill buffer with properly formatted INumber string.
+ \param buf to store the formatted string.
+ \param format format in sprintf style.
+ \param value the number to format.
+ \return length of string.
+*/
+int numberFormat (char *buf, const char *format, double value);
+
+/** \brief Fill buffer with properly formatted INumber string.
+ \param buf to store the formatted string.
+ \param format format in sprintf style.
+ \param value the number to format.
+ \return length of string.
+*/
+int numberFormat (char *buf, const char *format, double value);
+
+/** \brief Create an ISO 8601 formatted time stamp. The format is YYYY-MM-DDTHH:MM:SS
+ \return The formatted time stamp.
+*/
+const char *timestamp (void);
+
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/kstars/kstars/indi/indidevapi.h b/kstars/kstars/indi/indidevapi.h
new file mode 100644
index 00000000..3b6aacc6
--- /dev/null
+++ b/kstars/kstars/indi/indidevapi.h
@@ -0,0 +1,511 @@
+#if 0
+ INDI
+ Copyright (C) 2003 Elwood C. Downey
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#ifndef INDI_DEVAPI_H
+#define INDI_DEVAPI_H
+
+/** \file indidevapi.h
+ \brief Interface to the reference INDI C API device implementation on the Device Driver side.
+ \author Elwood C. Downey
+ \author Jasem Mutlaq
+
+ This file is divided into two main sections:\n
+ <ol><li> Functions the INDI device driver framework defines which the Driver may
+ call:</li>
+
+ <ul><li>IDxxx functions to send messages to an INDI client.</li>
+ <li>IExxx functions to implement the event driven model.</li>
+ <li>IUxxx functions to perform handy utility functions.</li></ul>
+
+ <li>Functions the INDI device driver framework calls which the Driver must
+ define:</li>
+
+ <ul><li>ISxxx to respond to messages from a Client.</li></ul></ol>
+*/
+
+
+/*******************************************************************************
+ * get the data structures
+ */
+
+#include "indiapi.h"
+
+/*******************************************************************************
+ *******************************************************************************
+ *
+ * Functions the INDI device driver framework defines which the Driver calls
+ *
+ *******************************************************************************
+ *******************************************************************************
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup d2cFunctions Functions Drivers call to define their Properties to Clients.
+ */
+/*@{*/
+
+/** \brief Tell client to create a text vector property.
+ \param t pointer to the vector text property to be defined.
+ \param msg message in printf style to send to the client. May be NULL.
+*/
+extern void IDDefText (const ITextVectorProperty *t, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 2, 3 ) ) )
+#endif
+;
+
+/** \brief Tell client to create a number number property.
+ \param n pointer to the vector number property to be defined.
+ \param msg message in printf style to send to the client. May be NULL.
+*/
+extern void IDDefNumber (const INumberVectorProperty *n, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 2, 3 ) ) )
+#endif
+;
+
+/** \brief Tell client to create a switch vector property.
+ \param s pointer to the vector switch property to be defined.
+ \param msg message in printf style to send to the client. May be NULL.
+*/
+extern void IDDefSwitch (const ISwitchVectorProperty *s, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 2, 3 ) ) )
+#endif
+;
+
+/** \brief Tell client to create a light vector property.
+ \param l pointer to the vector light property to be defined.
+ \param msg message in printf style to send to the client. May be NULL.
+*/
+extern void IDDefLight (const ILightVectorProperty *l, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 2, 3 ) ) )
+#endif
+;
+
+/** \brief Tell client to create a BLOB vector property.
+ \param b pointer to the vector BLOB property to be defined.
+ \param msg message in printf style to send to the client. May be NULL.
+ */
+extern void IDDefBLOB (const IBLOBVectorProperty *b, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 2, 3 ) ) )
+#endif
+;
+
+
+/*@}*/
+
+/**
+ * \defgroup d2cuFunctions Functions Drivers call to tell Clients of new values for existing Properties.
+ */
+/*@{*/
+
+/** \brief Tell client to update an existing text vector property.
+ \param t pointer to the vector text property.
+ \param msg message in printf style to send to the client. May be NULL.
+*/
+extern void IDSetText (const ITextVectorProperty *t, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 2, 3 ) ) )
+#endif
+;
+
+/** \brief Tell client to update an existing number vector property.
+ \param n pointer to the vector number property.
+ \param msg message in printf style to send to the client. May be NULL.
+*/
+extern void IDSetNumber (const INumberVectorProperty *n, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 2, 3 ) ) )
+#endif
+;
+
+/** \brief Tell client to update an existing switch vector property.
+ \param s pointer to the vector switch property.
+ \param msg message in printf style to send to the client. May be NULL.
+*/
+extern void IDSetSwitch (const ISwitchVectorProperty *s, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 2, 3 ) ) )
+#endif
+;
+
+/** \brief Tell client to update an existing light vector property.
+ \param l pointer to the vector light property.
+ \param msg message in printf style to send to the client. May be NULL.
+*/
+extern void IDSetLight (const ILightVectorProperty *l, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 2, 3 ) ) )
+#endif
+;
+
+/** \brief Tell client to update an existing BLOB vector property.
+ \param b pointer to the vector BLOB property.
+ \param msg message in printf style to send to the client. May be NULL.
+ */
+extern void IDSetBLOB (const IBLOBVectorProperty *b, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 2, 3 ) ) )
+#endif
+;
+
+/*@}*/
+
+
+/** \brief Function Drivers call to send log messages to Clients.
+
+ If dev is specified the Client shall associate the message with that device; if dev is NULL the Client shall treat the message as generic from no specific Device.
+
+ \param dev device name
+ \param msg message in printf style to send to the client.
+*/
+extern void IDMessage (const char *dev, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 2, 3 ) ) )
+#endif
+;
+
+/** \brief Function Drivers call to inform Clients a Property is no longer available, or the entire device is gone if name is NULL.
+
+ \param dev device name. If device name is NULL, the entire device will be deleted.
+ \param name property name to be deleted.
+ \param msg message in printf style to send to the client.
+*/
+extern void IDDelete (const char *dev, const char *name, const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 3, 4 ) ) )
+#endif
+;
+
+/** \brief Function Drivers call to log a message locally.
+
+ The message is not sent to any Clients.
+
+ \param msg message in printf style to send to the client.
+*/
+extern void IDLog (const char *msg, ...)
+#ifdef __GNUC__
+ __attribute__ ( ( format( printf, 1, 2 ) ) )
+#endif
+;
+
+/**
+ * \defgroup deventFunctions Functions Drivers call to register with the INDI event utilities.
+
+ Callbacks are called when a read on a file descriptor will not block. Timers are called once after a specified interval. Workprocs are called when there is nothing else to do. The "Add" functions return a unique id for use with their corresponding "Rm" removal function. An arbitrary pointer may be specified when a function is registered which will be stored and forwarded unchanged when the function is later invoked.
+ */
+/*@{*/
+
+ /* signature of a callback, timout caller and work procedure function */
+
+/** \typedef IE_CBF Signature of a callback. */
+typedef void (IE_CBF) (int readfiledes, void *userpointer);
+/** \typedef IE_CBF Signature of a timeout caller. */
+typedef void (IE_TCF) (void *userpointer);
+/** \typedef IE_CBF Signature of a work procedure function. */
+typedef void (IE_WPF) (void *userpointer);
+
+/* functions to add and remove callbacks, timers and work procedures */
+
+/** \brief Register a new callback, \e fp, to be called with \e userpointer as argument when \e readfiledes is ready.
+*
+* \param readfiledes file descriptor.
+* \param fp a pointer to the callback function.
+* \param userpointer a pointer to be passed to the callback function when called.
+* \return a unique callback id for use with IERmCallback().
+*/
+extern int IEAddCallback (int readfiledes, IE_CBF *fp, void *userpointer);
+
+/** \brief Remove a callback function.
+*
+* \param callbackid the callback ID returned from IEAddCallback()
+*/
+extern void IERmCallback (int callbackid);
+
+/** \brief Register a new timer function, \e fp, to be called with \e ud as argument after \e ms.
+
+ Add to list in order of decreasing time from epoch, ie, last entry runs soonest. The timer will only invoke the callback function \b once. You need to call addTimer again if you want to repeat the process.
+*
+* \param millisecs timer period in milliseconds.
+* \param fp a pointer to the callback function.
+* \param userpointer a pointer to be passed to the callback function when called.
+* \return a unique id for use with IERmTimer().
+*/
+extern int IEAddTimer (int millisecs, IE_TCF *fp, void *userpointer);
+
+/** \brief Remove the timer with the given \e timerid, as returned from IEAddTimer.
+*
+* \param timerid the timer callback ID returned from IEAddTimer().
+*/
+extern void IERmTimer (int timerid);
+
+/** \brief Add a new work procedure, fp, to be called with ud when nothing else to do.
+*
+* \param fp a pointer to the work procedure callback function.
+* \param userpointer a pointer to be passed to the callback function when called.
+* \return a unique id for use with IERmWorkProc().
+*/
+extern int IEAddWorkProc (IE_WPF *fp, void *userpointer);
+
+/** \brief Remove the work procedure with the given \e workprocid, as returned from IEAddWorkProc().
+*
+* \param workprocid the work procedure callback ID returned from IEAddWorkProc().
+*/
+extern void IERmWorkProc (int workprocid);
+
+/*@}*/
+
+/**
+ * \defgroup dutilFunctions Functions Drivers call to perform handy utility functions.
+
+ These do not communicate with the Client in any way.
+ */
+/*@{*/
+
+
+/** \brief Find an IText member in a vector text property.
+*
+* \param tp a pointer to a text vector property.
+* \param name the name of the member to search for.
+* \return a pointer to an IText member on match, or NULL if nothing is found.
+*/
+extern IText *IUFindText (const ITextVectorProperty *tp, const char *name);
+
+/** \brief Find an INumber member in a number text property.
+*
+* \param tp a pointer to a number vector property.
+* \param name the name of the member to search for.
+* \return a pointer to an INumber member on match, or NULL if nothing is found.
+*/
+extern INumber *IUFindNumber(const INumberVectorProperty *tp, const char *name);
+
+/** \brief Find an ISwitch member in a vector switch property.
+*
+* \param tp a pointer to a switch vector property.
+* \param name the name of the member to search for.
+* \return a pointer to an ISwitch member on match, or NULL if nothing is found.
+*/
+extern ISwitch *IUFindSwitch(const ISwitchVectorProperty *tp, const char *name);
+
+/** \brief Returns the first ON switch it finds in the vector switch property.
+
+* \note This is only valid for ISR_1OFMANY mode. That is, when only one switch out of many is allowed to be ON. Do not use this function if you can have multiple ON switches in the same vector property.
+*
+* \param tp a pointer to a switch vector property.
+* \return a pointer to the \e first ON ISwitch member if found. If all switches are off, NULL is returned.
+*/
+extern ISwitch *IUFindOnSwitch (const ISwitchVectorProperty *tp);
+
+/** \brief Reset all switches in a switch vector property to OFF.
+*
+* \param svp a pointer to a switch vector property.
+*/
+extern void IUResetSwitches(const ISwitchVectorProperty *svp);
+
+/** \brief Update all switches in a switch vector property.
+*
+* \param svp a pointer to a switch vector property.
+* \param states the states of the new ISwitch members.
+* \param names the names of the ISwtich members to update.
+* \param n the number of ISwitch members to update.
+* \return 0 if update successful, -1 otherwise.
+*/
+extern int IUUpdateSwitches(ISwitchVectorProperty *svp, ISState *states, char *names[], int n);
+
+/** \brief Update all numbers in a number vector property.
+*
+* \param nvp a pointer to a number vector property.
+* \param values the states of the new INumber members.
+* \param names the names of the INumber members to update.
+* \param n the number of INumber members to update.
+* \return 0 if update successful, -1 otherwise. Update will fail if values are out of scope, or in case of property name mismatch.
+*/
+extern int IUUpdateNumbers(INumberVectorProperty *nvp, double values[], char *names[], int n);
+
+/** \brief Function to update the min and max elements of a number in the client
+ \param nvp pointer to an INumberVectorProperty.
+ */
+extern void IUUpdateMinMax(INumberVectorProperty *nvp);
+
+/** \brief Function to reliably save new text in a IText.
+ \param tp pointer to an IText member.
+ \param newtext the new text to be saved
+*/
+extern void IUSaveText (IText *tp, const char *newtext);
+
+/** \brief Assign attributes for a switch property. The switch's auxilary elements will be set to NULL.
+ \param sp pointer a switch property to fill
+ \param name the switch name
+ \param label the switch label
+ \param s the switch state (ISS_ON or ISS_OFF)
+*/
+extern void fillSwitch(ISwitch *sp, const char *name, const char * label, ISState s);
+
+/** \brief Assign attributes for a number property. The number's auxilary elements will be set to NULL.
+ \param np pointer a number property to fill
+ \param name the number name
+ \param label the number label
+ \param format the number format in printf style (e.g. "%02d")
+ \param min the minimum possible value
+ \param max the maximum possible value
+ \param step the step used to climb from minimum value to maximum value
+ \param value the number's current value
+*/
+extern void fillNumber(INumber *np, const char *name, const char * label, const char *format, double min, double max, double step, double value);
+
+/** \brief Assign attributes for a text property. The text's auxilary elements will be set to NULL.
+ \param tp pointer a text property to fill
+ \param name the text name
+ \param label the text label
+ \param initialText the initial text
+*/
+extern void fillText(IText *tp, const char *name, const char * label, const char *initialText);
+
+/** \brief Assign attributes for a switch vector property. The vector's auxilary elements will be set to NULL.
+ \param svp pointer a switch vector property to fill
+ \param sp pointer to an array of switches
+ \param nsp the dimension of sp
+ \param dev the device name this vector property belongs to
+ \param name the vector property name
+ \param label the vector property label
+ \param group the vector property group
+ \param p the vector property permission
+ \param r the switches behavior
+ \param timeout vector property timeout in seconds
+ \param s the vector property initial state.
+*/
+extern void fillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char * dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s);
+
+/** \brief Assign attributes for a number vector property. The vector's auxilary elements will be set to NULL.
+ \param nvp pointer a number vector property to fill
+ \param np pointer to an array of numbers
+ \param nnp the dimension of np
+ \param dev the device name this vector property belongs to
+ \param name the vector property name
+ \param label the vector property label
+ \param group the vector property group
+ \param p the vector property permission
+ \param timeout vector property timeout in seconds
+ \param s the vector property initial state.
+*/
+extern void fillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char * dev, const char *name, const char *label, const char* group, IPerm p, double timeout, IPState s);
+
+/** \brief Assign attributes for a text vector property. The vector's auxilary elements will be set to NULL.
+ \param tvp pointer a text vector property to fill
+ \param tp pointer to an array of texts
+ \param ntp the dimension of tp
+ \param dev the device name this vector property belongs to
+ \param name the vector property name
+ \param label the vector property label
+ \param group the vector property group
+ \param p the vector property permission
+ \param timeout vector property timeout in seconds
+ \param s the vector property initial state.
+*/
+extern void fillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char * dev, const char *name, const char *label, const char* group, IPerm p, double timeout, IPState s);
+
+/*@}*/
+
+/*******************************************************************************
+ *******************************************************************************
+ *
+ * Functions the INDI Device Driver framework calls which the Driver must
+ * define.
+ *
+ *******************************************************************************
+ *******************************************************************************
+ */
+
+
+/** \brief Function defined by Drivers that is called when a Client asks for the definitions of all Properties this Driver supports for the given device.
+ \param dev the name of the device.
+*/
+extern void ISGetProperties (const char *dev);
+
+
+/**
+ * \defgroup dcuFunctions Functions defined by Drivers that are called when a Client wishes to set different values named members of the given vector Property.
+
+ The values and their names are parallel arrays of n elements each.
+*/
+/*@{*/
+
+/** \brief Update the value of an existing text vector property.
+ \param dev the name of the device.
+ \param name the name of the text vector property to update.
+ \param texts an array of text values.
+ \param names parallel names to the array of text values.
+ \param n the dimension of texts[].
+ \note You do not need to call this function, it is called by INDI when new text values arrive from the client.
+*/
+extern void ISNewText (const char *dev, const char *name, char *texts[],
+ char *names[], int n);
+
+/** \brief Update the value of an existing number vector property.
+ \param dev the name of the device.
+ \param name the name of the number vector property to update.
+ \param doubles an array of number values.
+ \param names parallel names to the array of number values.
+ \param n the dimension of doubles[].
+ \note You do not need to call this function, it is called by INDI when new number values arrive from the client.
+*/
+extern void ISNewNumber (const char *dev, const char *name, double *doubles,
+ char *names[], int n);
+
+/** \brief Update the value of an existing switch vector property.
+ \param dev the name of the device.
+ \param name the name of the switch vector property to update.
+ \param states an array of switch states.
+ \param names parallel names to the array of switch states.
+ \param n the dimension of states[].
+ \note You do not need to call this function, it is called by INDI when new switch values arrive from the client.
+*/
+extern void ISNewSwitch (const char *dev, const char *name, ISState *states,
+ char *names[], int n);
+
+/** \brief Update data of an existing blob vector property.
+ \param dev the name of the device.
+ \param name the name of the blob vector property to update.
+ \param sizes an array of blob sizes in bytes.
+ \param blobs the blob data array in bytes
+ \param formats Blob data format (e.g. fits.z).
+ \param names names of blob members to update.
+ \param n the number of blobs to update.
+ \note You do not need to call this function, it is called by INDI when new blob values arrive from the client.
+ e.g. BLOB element with name names[0] has data located in blobs[0] with size sizes[0] and format formats[0].
+*/
+
+extern void ISNewBLOB (const char *dev, const char *name, int sizes[],
+ char *blobs[], char *formats[], char *names[], int n);
+
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/kstars/kstars/indi/indidrivermain.c b/kstars/kstars/indi/indidrivermain.c
new file mode 100644
index 00000000..4f375ca4
--- /dev/null
+++ b/kstars/kstars/indi/indidrivermain.c
@@ -0,0 +1,1250 @@
+#if 0
+ INDI
+ Copyright (C) 2003 Elwood C. Downey
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+/* main() for one INDI driver process.
+ * Drivers define IS*() functions we call to deliver INDI XML arriving on stdin.
+ * Drivers call ID*() functions to send INDI XML commands to stdout.
+ * Drivers call IE*() functions to build an event-driver program.
+ * Drivers call IU*() functions to perform various common utility tasks.
+ * Troubles are reported on stderr then we exit.
+ *
+ * This requires liblilxml.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "lilxml.h"
+#include "base64.h"
+#include "eventloop.h"
+#include "indidevapi.h"
+#include "indicom.h"
+
+static void usage(void);
+static void clientMsgCB(int fd, void *arg);
+static int dispatch (XMLEle *root, char msg[]);
+static int crackDN (XMLEle *root, char **dev, char **name, char msg[]);
+const char *pstateStr(IPState s);
+const char *sstateStr(ISState s);
+const char *ruleStr(ISRule r);
+const char *permStr(IPerm p);
+
+static int nroCheck; /* # of elements in roCheck */
+static int verbose; /* chatty */
+char *me; /* a.out name */
+static LilXML *clixml; /* XML parser context */
+
+/* insure RO properties are never modified. RO Sanity Check */
+typedef struct
+{
+ char propName[MAXINDINAME];
+ IPerm perm;
+} ROSC;
+
+static ROSC *roCheck;
+
+int
+main (int ac, char *av[])
+{
+ setgid( getgid() );
+ setuid( getuid() );
+ if (geteuid() != getuid())
+ exit(255);
+
+ /* save handy pointer to our base name */
+ for (me = av[0]; av[0][0]; av[0]++)
+ if (av[0][0] == '/')
+ me = &av[0][1];
+
+ /* crack args */
+ while (--ac && (*++av)[0] == '-')
+ while (*++(*av))
+ switch (*(*av)) {
+ case 'v': /* verbose */
+ verbose++;
+ break;
+ default:
+ usage();
+ }
+
+ /* ac remaining args starting at av[0] */
+ if (ac > 0)
+ usage();
+
+ /* init */
+ clixml = newLilXML();
+ addCallback (0, clientMsgCB, NULL);
+
+ nroCheck = 0;
+ roCheck = NULL;
+
+ /* service client */
+ eventLoop();
+
+ /* eh?? */
+ fprintf (stderr, "%s: inf loop ended\n", me);
+ return (1);
+}
+
+/* functions we define that drivers may call */
+
+/* tell client to create a text vector property */
+void
+IDDefText (const ITextVectorProperty *tvp, const char *fmt, ...)
+{
+ int i;
+ ROSC *SC;
+
+ printf ("<defTextVector\n");
+ printf (" device='%s'\n", tvp->device);
+ printf (" name='%s'\n", tvp->name);
+ printf (" label='%s'\n", tvp->label);
+ printf (" group='%s'\n", tvp->group);
+ printf (" state='%s'\n", pstateStr(tvp->s));
+ printf (" perm='%s'\n", permStr(tvp->p));
+ printf (" timeout='%g'\n", tvp->timeout);
+ printf (" timestamp='%s'\n", timestamp());
+ if (fmt) {
+ va_list ap;
+ va_start (ap, fmt);
+ printf (" message='");
+ vprintf (fmt, ap);
+ printf ("'\n");
+ va_end (ap);
+ }
+ printf (">\n");
+
+ for (i = 0; i < tvp->ntp; i++) {
+ IText *tp = &tvp->tp[i];
+ printf (" <defText\n");
+ printf (" name='%s'\n", tp->name);
+ printf (" label='%s'>\n", tp->label);
+ printf (" %s\n", tp->text ? tp->text : "");
+ printf (" </defText>\n");
+ }
+
+ printf ("</defTextVector>\n");
+
+ /* Add this property to insure proper sanity check */
+ roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
+ : (ROSC *) malloc ( sizeof(ROSC));
+ SC = &roCheck[nroCheck++];
+
+ strcpy(SC->propName, tvp->name);
+ SC->perm = tvp->p;
+
+ fflush (stdout);
+}
+
+/* tell client to create a new numeric vector property */
+void
+IDDefNumber (const INumberVectorProperty *n, const char *fmt, ...)
+{
+ int i;
+ ROSC *SC;
+
+ printf ("<defNumberVector\n");
+ printf (" device='%s'\n", n->device);
+ printf (" name='%s'\n", n->name);
+ printf (" label='%s'\n", n->label);
+ printf (" group='%s'\n", n->group);
+ printf (" state='%s'\n", pstateStr(n->s));
+ printf (" perm='%s'\n", permStr(n->p));
+ printf (" timeout='%g'\n", n->timeout);
+ printf (" timestamp='%s'\n", timestamp());
+ if (fmt) {
+ va_list ap;
+ va_start (ap, fmt);
+ printf (" message='");
+ vprintf (fmt, ap);
+ printf ("'\n");
+ va_end (ap);
+ }
+ printf (">\n");
+
+ for (i = 0; i < n->nnp; i++) {
+ INumber *np = &n->np[i];
+ printf (" <defNumber\n");
+ printf (" name='%s'\n", np->name);
+ printf (" label='%s'\n", np->label);
+ printf (" format='%s'\n", np->format);
+ printf (" min='%g'\n", np->min);
+ printf (" max='%g'\n", np->max);
+ printf (" step='%g'>\n", np->step);
+ printf (" %g\n", np->value);
+ printf (" </defNumber>\n");
+ }
+
+ printf ("</defNumberVector>\n");
+
+ /* Add this property to insure proper sanity check */
+ roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
+ : (ROSC *) malloc ( sizeof(ROSC));
+ SC = &roCheck[nroCheck++];
+
+ strcpy(SC->propName, n->name);
+ SC->perm = n->p;
+
+ fflush (stdout);
+}
+
+/* tell client to create a new switch vector property */
+void
+IDDefSwitch (const ISwitchVectorProperty *s, const char *fmt, ...)
+
+{
+ int i;
+ ROSC *SC;
+
+ printf ("<defSwitchVector\n");
+ printf (" device='%s'\n", s->device);
+ printf (" name='%s'\n", s->name);
+ printf (" label='%s'\n", s->label);
+ printf (" group='%s'\n", s->group);
+ printf (" state='%s'\n", pstateStr(s->s));
+ printf (" perm='%s'\n", permStr(s->p));
+ printf (" rule='%s'\n", ruleStr (s->r));
+ printf (" timeout='%g'\n", s->timeout);
+ printf (" timestamp='%s'\n", timestamp());
+ if (fmt) {
+ va_list ap;
+ va_start (ap, fmt);
+ printf (" message='");
+ vprintf (fmt, ap);
+ printf ("'\n");
+ va_end (ap);
+ }
+ printf (">\n");
+
+ for (i = 0; i < s->nsp; i++) {
+ ISwitch *sp = &s->sp[i];
+ printf (" <defSwitch\n");
+ printf (" name='%s'\n", sp->name);
+ printf (" label='%s'>\n", sp->label);
+ printf (" %s\n", sstateStr(sp->s));
+ printf (" </defSwitch>\n");
+ }
+
+ printf ("</defSwitchVector>\n");
+
+ /* Add this property to insure proper sanity check */
+ roCheck = roCheck ? (ROSC *) realloc ( roCheck, sizeof(ROSC) * (nroCheck+1))
+ : (ROSC *) malloc ( sizeof(ROSC));
+ SC = &roCheck[nroCheck++];
+
+ strcpy(SC->propName, s->name);
+ SC->perm = s->p;
+
+ fflush (stdout);
+}
+
+/* tell client to create a new lights vector property */
+void
+IDDefLight (const ILightVectorProperty *lvp, const char *fmt, ...)
+{
+ int i;
+
+ printf ("<defLightVector\n");
+ printf (" device='%s'\n", lvp->device);
+ printf (" name='%s'\n", lvp->name);
+ printf (" label='%s'\n", lvp->label);
+ printf (" group='%s'\n", lvp->group);
+ printf (" state='%s'\n", pstateStr(lvp->s));
+ printf (" timestamp='%s'\n", timestamp());
+ if (fmt) {
+ va_list ap;
+ va_start (ap, fmt);
+ printf (" message='");
+ vprintf (fmt, ap);
+ printf ("'\n");
+ va_end (ap);
+ }
+ printf (">\n");
+
+ for (i = 0; i < lvp->nlp; i++) {
+ ILight *lp = &lvp->lp[i];
+ printf (" <defLight\n");
+ printf (" name='%s'\n", lp->name);
+ printf (" label='%s'>\n", lp->label);
+ printf (" %s\n", pstateStr(lp->s));
+ printf (" </defLight>\n");
+ }
+
+ printf ("</defLightVector>\n");
+ fflush (stdout);
+}
+
+/* tell client to create a new BLOB vector property */
+void
+IDDefBLOB (const IBLOBVectorProperty *b, const char *fmt, ...)
+{
+ int i;
+
+ printf ("<defBLOBVector\n");
+ printf (" device='%s'\n", b->device);
+ printf (" name='%s'\n", b->name);
+ printf (" label='%s'\n", b->label);
+ printf (" group='%s'\n", b->group);
+ printf (" state='%s'\n", pstateStr(b->s));
+ printf (" perm='%s'\n", permStr(b->p));
+ printf (" timeout='%g'\n", b->timeout);
+ printf (" timestamp='%s'\n", timestamp());
+ if (fmt) {
+ va_list ap;
+ va_start (ap, fmt);
+ printf (" message='");
+ vprintf (fmt, ap);
+ printf ("'\n");
+ va_end (ap);
+ }
+ printf (">\n");
+
+ for (i = 0; i < b->nbp; i++) {
+ IBLOB *bp = &b->bp[i];
+ printf (" <defBLOB\n");
+ printf (" name='%s'\n", bp->name);
+ printf (" label='%s'\n", bp->label);
+ printf (" />\n");
+ }
+
+ printf ("</defBLOBVector>\n");
+ fflush (stdout);
+}
+
+/* tell client to update an existing text vector property */
+void
+IDSetText (const ITextVectorProperty *tvp, const char *fmt, ...)
+{
+ int i;
+
+ printf ("<setTextVector\n");
+ printf (" device='%s'\n", tvp->device);
+ printf (" name='%s'\n", tvp->name);
+ printf (" state='%s'\n", pstateStr(tvp->s));
+ printf (" timeout='%g'\n", tvp->timeout);
+ printf (" timestamp='%s'\n", timestamp());
+ if (fmt) {
+ va_list ap;
+ va_start (ap, fmt);
+ printf (" message='");
+ vprintf (fmt, ap);
+ printf ("'\n");
+ va_end (ap);
+ }
+ printf (">\n");
+
+ for (i = 0; i < tvp->ntp; i++) {
+ IText *tp = &tvp->tp[i];
+ printf (" <oneText name='%s'>\n", tp->name);
+ printf (" %s\n", tp->text ? tp->text : "");
+ printf (" </oneText>\n");
+ }
+
+ printf ("</setTextVector>\n");
+ fflush (stdout);
+}
+
+/* tell client to update an existing numeric vector property */
+void
+IDSetNumber (const INumberVectorProperty *nvp, const char *fmt, ...)
+{
+ int i;
+
+ printf ("<setNumberVector\n");
+ printf (" device='%s'\n", nvp->device);
+ printf (" name='%s'\n", nvp->name);
+ printf (" state='%s'\n", pstateStr(nvp->s));
+ printf (" timeout='%g'\n", nvp->timeout);
+ printf (" timestamp='%s'\n", timestamp());
+ if (fmt) {
+ va_list ap;
+ va_start (ap, fmt);
+ printf (" message='");
+ vprintf (fmt, ap);
+ printf ("'\n");
+ va_end (ap);
+ }
+ printf (">\n");
+
+ for (i = 0; i < nvp->nnp; i++) {
+ INumber *np = &nvp->np[i];
+ printf (" <oneNumber name='%s'>\n", np->name);
+ printf (" %.10g\n", np->value);
+ printf (" </oneNumber>\n");
+ }
+
+ printf ("</setNumberVector>\n");
+ fflush (stdout);
+}
+
+/* tell client to update an existing switch vector property */
+void
+IDSetSwitch (const ISwitchVectorProperty *svp, const char *fmt, ...)
+{
+ int i;
+
+ printf ("<setSwitchVector\n");
+ printf (" device='%s'\n", svp->device);
+ printf (" name='%s'\n", svp->name);
+ printf (" state='%s'\n", pstateStr(svp->s));
+ printf (" timeout='%g'\n", svp->timeout);
+ printf (" timestamp='%s'\n", timestamp());
+ if (fmt) {
+ va_list ap;
+ va_start (ap, fmt);
+ printf (" message='");
+ vprintf (fmt, ap);
+ printf ("'\n");
+ va_end (ap);
+ }
+ printf (">\n");
+
+ for (i = 0; i < svp->nsp; i++) {
+ ISwitch *sp = &svp->sp[i];
+ printf (" <oneSwitch name='%s'>\n", sp->name);
+ printf (" %s\n", sstateStr(sp->s));
+ printf (" </oneSwitch>\n");
+ }
+
+ printf ("</setSwitchVector>\n");
+ fflush (stdout);
+}
+
+/* tell client to update an existing lights vector property */
+void
+IDSetLight (const ILightVectorProperty *lvp, const char *fmt, ...)
+{
+ int i;
+
+ printf ("<setLightVector\n");
+ printf (" device='%s'\n", lvp->device);
+ printf (" name='%s'\n", lvp->name);
+ printf (" state='%s'\n", pstateStr(lvp->s));
+ printf (" timestamp='%s'\n", timestamp());
+ if (fmt) {
+ va_list ap;
+ va_start (ap, fmt);
+ printf (" message='");
+ vprintf (fmt, ap);
+ printf ("'\n");
+ va_end (ap);
+ }
+ printf (">\n");
+
+ for (i = 0; i < lvp->nlp; i++) {
+ ILight *lp = &lvp->lp[i];
+ printf (" <oneLight name='%s'>\n", lp->name);
+ printf (" %s\n", pstateStr(lp->s));
+ printf (" </oneLight>\n");
+ }
+
+ printf ("</setLightVector>\n");
+ fflush (stdout);
+}
+
+/* tell client to update an existing BLOB vector property */
+void
+IDSetBLOB (const IBLOBVectorProperty *bvp, const char *fmt, ...)
+{
+ int i;
+
+ printf ("<setBLOBVector\n");
+ printf (" device='%s'\n", bvp->device);
+ printf (" name='%s'\n", bvp->name);
+ printf (" state='%s'\n", pstateStr(bvp->s));
+ printf (" timeout='%g'\n", bvp->timeout);
+ printf (" timestamp='%s'\n", timestamp());
+ if (fmt) {
+ va_list ap;
+ va_start (ap, fmt);
+ printf (" message='");
+ vprintf (fmt, ap);
+ printf ("'\n");
+ va_end (ap);
+ }
+ printf (">\n");
+
+ for (i = 0; i < bvp->nbp; i++) {
+ IBLOB *bp = &bvp->bp[i];
+ char *encblob;
+ int j, l;
+
+ printf (" <oneBLOB\n");
+ printf (" name='%s'\n", bp->name);
+ printf (" size='%d'\n", bp->size);
+ printf (" format='%s'>\n", bp->format);
+
+ encblob = malloc (4*bp->bloblen/3+4);
+ l = to64frombits(encblob, bp->blob, bp->bloblen);
+ for (j = 0; j < l; j += 72)
+ printf ("%.72s\n", encblob+j);
+ free (encblob);
+
+ printf (" </oneBLOB>\n");
+ }
+
+ printf ("</setBLOBVector>\n");
+ fflush (stdout);
+}
+
+/* tell client to update min/max elements of an existing number vector property */
+void IUUpdateMinMax(INumberVectorProperty *nvp)
+{
+ int i;
+
+ printf ("<setNumberVector\n");
+ printf (" device='%s'\n", nvp->device);
+ printf (" name='%s'\n", nvp->name);
+ printf (" state='%s'\n", pstateStr(nvp->s));
+ printf (" timeout='%g'\n", nvp->timeout);
+ printf (" timestamp='%s'\n", timestamp());
+ printf (">\n");
+
+ for (i = 0; i < nvp->nnp; i++) {
+ INumber *np = &nvp->np[i];
+ printf (" <oneNumber name='%s'\n", np->name);
+ printf (" min='%g'\n", np->min);
+ printf (" max='%g'\n", np->max);
+ printf (" step='%g'\n", np->step);
+ printf(">\n");
+ printf (" %g\n", np->value);
+ printf (" </oneNumber>\n");
+ }
+
+ printf ("</setNumberVector>\n");
+ fflush (stdout);
+}
+
+/* send client a message for a specific device or at large if !dev */
+void
+IDMessage (const char *dev, const char *fmt, ...)
+{
+ printf ("<message\n");
+ if (dev)
+ printf (" device='%s'\n", dev);
+ printf (" timestamp='%s'\n", timestamp());
+ if (fmt) {
+ va_list ap;
+ va_start (ap, fmt);
+ printf (" message='");
+ vprintf (fmt, ap);
+ printf ("'\n");
+ va_end (ap);
+ }
+ printf ("/>\n");
+ fflush (stdout);
+}
+
+/* tell Client to delete the property with given name on given device, or
+ * entire device if !name
+ */
+void
+IDDelete (const char *dev, const char *name, const char *fmt, ...)
+{
+ printf ("<delProperty\n device='%s'\n", dev);
+ if (name)
+ printf (" name='%s'\n", name);
+ printf (" timestamp='%s'\n", timestamp());
+ if (fmt) {
+ va_list ap;
+ va_start (ap, fmt);
+ printf (" message='");
+ vprintf (fmt, ap);
+ printf ("'\n");
+ va_end (ap);
+ }
+ printf ("/>\n");
+ fflush (stdout);
+}
+
+/* log message locally.
+ * this has nothing to do with XML or any Clients.
+ */
+void
+IDLog (const char *fmt, ...)
+{
+ va_list ap;
+ fprintf (stderr, "%s ", timestamp());
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+}
+
+/* "INDI" wrappers to the more generic eventloop facility. */
+
+int
+IEAddCallback (int readfiledes, IE_CBF *fp, void *p)
+{
+ return (addCallback (readfiledes, (CBF*)fp, p));
+}
+
+void
+IERmCallback (int callbackid)
+{
+ rmCallback (callbackid);
+}
+
+int
+IEAddTimer (int millisecs, IE_TCF *fp, void *p)
+{
+ return (addTimer (millisecs, (TCF*)fp, p));
+}
+
+void
+IERmTimer (int timerid)
+{
+ rmTimer (timerid);
+}
+
+int
+IEAddWorkProc (IE_WPF *fp, void *p)
+{
+ return (addWorkProc ((WPF*)fp, p));
+}
+
+void
+IERmWorkProc (int workprocid)
+{
+ rmWorkProc (workprocid);
+}
+
+/* find a member of an IText vector, else NULL */
+IText *
+IUFindText (const ITextVectorProperty *tvp, const char *name)
+{
+ int i;
+
+ for (i = 0; i < tvp->ntp; i++)
+ if (strcmp (tvp->tp[i].name, name) == 0)
+ return (&tvp->tp[i]);
+ fprintf (stderr, "No IText '%s' in %s.%s\n",name,tvp->device,tvp->name);
+ return (NULL);
+}
+
+/* find a member of an INumber vector, else NULL */
+INumber *
+IUFindNumber(const INumberVectorProperty *nvp, const char *name)
+{
+ int i;
+
+ for (i = 0; i < nvp->nnp; i++)
+ if (strcmp (nvp->np[i].name, name) == 0)
+ return (&nvp->np[i]);
+ fprintf(stderr,"No INumber '%s' in %s.%s\n",name,nvp->device,nvp->name);
+ return (NULL);
+}
+
+/* find a member of an ISwitch vector, else NULL */
+ISwitch *
+IUFindSwitch(const ISwitchVectorProperty *svp, const char *name)
+{
+ int i;
+
+ for (i = 0; i < svp->nsp; i++)
+ if (strcmp (svp->sp[i].name, name) == 0)
+ return (&svp->sp[i]);
+ fprintf(stderr,"No ISwitch '%s' in %s.%s\n",name,svp->device,svp->name);
+ return (NULL);
+}
+
+/* find an ON member of an ISwitch vector, else NULL.
+ * N.B. user must make sense of result with ISRule in mind.
+ */
+ISwitch *
+IUFindOnSwitch(const ISwitchVectorProperty *svp)
+{
+ int i;
+
+ for (i = 0; i < svp->nsp; i++)
+ if (svp->sp[i].s == ISS_ON)
+ return (&svp->sp[i]);
+ fprintf(stderr, "No ISwitch On in %s.%s\n", svp->device, svp->name);
+ return (NULL);
+}
+
+/* Set all switches to off */
+void
+IUResetSwitches(const ISwitchVectorProperty *svp)
+{
+ int i;
+
+ for (i = 0; i < svp->nsp; i++)
+ svp->sp[i].s = ISS_OFF;
+}
+
+/* Update property switches in accord with states and names. */
+int
+IUUpdateSwitches(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
+{
+ int i=0;
+
+ ISwitch *sp;
+
+ for (i = 0; i < n ; i++)
+ {
+ sp = IUFindSwitch(svp, names[i]);
+
+ if (!sp)
+ {
+ svp->s = IPS_IDLE;
+ IDSetSwitch(svp, "Error: %s is not a member of %s property.", names[i], svp->name);
+ return -1;
+ }
+
+ sp->s = states[i];
+ }
+
+ return 0;
+
+}
+
+/* Update property numbers in accord with values and names */
+int IUUpdateNumbers(INumberVectorProperty *nvp, double values[], char *names[], int n)
+{
+ int i=0;
+
+ INumber *np;
+
+ for (i = 0; i < n; i++)
+ {
+ np = IUFindNumber(nvp, names[i]);
+ if (!np)
+ {
+ nvp->s = IPS_IDLE;
+ IDSetNumber(nvp, "Error: %s is not a member of %s property.", names[i], nvp->name);
+ return -1;
+ }
+
+ if (values[i] < np->min || values[i] > np->max)
+ {
+ nvp->s = IPS_IDLE;
+ IDSetNumber(nvp, "Error: Invalid range. Valid range is from %g to %g", np->min, np->max);
+ return -1;
+ }
+
+ }
+
+ /* First loop checks for error, second loop set all values atomically*/
+ for (i=0; i < n; i++)
+ {
+ np = IUFindNumber(nvp, names[i]);
+ np->value = values[i];
+ }
+
+ return 0;
+
+}
+
+/* save malloced copy of newtext in tp->text, reusing if not first time */
+void
+IUSaveText (IText *tp, const char *newtext)
+{
+ /* seed for realloc */
+ if (tp->text == NULL)
+ tp->text = malloc (1);
+
+ /* copy in fresh string */
+ tp->text = strcpy (realloc (tp->text, strlen(newtext)+1), newtext);
+}
+
+void fillSwitch(ISwitch *sp, const char *name, const char * label, ISState s)
+{
+ strcpy(sp->name, name);
+ strcpy(sp->label, label);
+ sp->s = s;
+ sp->svp = NULL;
+ sp->aux = NULL;
+}
+
+void fillNumber(INumber *np, const char *name, const char * label, const char *format, double min, double max, double step, double value)
+{
+
+ strcpy(np->name, name);
+ strcpy(np->label, label);
+ strcpy(np->format, format);
+
+ np->min = min;
+ np->max = max;
+ np->step = step;
+ np->value = value;
+ np->nvp = NULL;
+ np->aux0 = NULL;
+ np->aux1 = NULL;
+}
+
+void fillText(IText *tp, const char *name, const char * label, const char *initialText)
+{
+
+ strcpy(tp->name, name);
+ strcpy(tp->label, label);
+ tp->text = NULL;
+ tp->tvp = NULL;
+ tp->aux0 = NULL;
+ tp->aux1 = NULL;
+
+ IUSaveText(tp, initialText);
+
+}
+
+void fillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char * dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
+{
+ strcpy(svp->device, dev);
+ strcpy(svp->name, name);
+ strcpy(svp->label, label);
+ strcpy(svp->group, group);
+ strcpy(svp->timestamp, "");
+
+ svp->p = p;
+ svp->r = r;
+ svp->timeout = timeout;
+ svp->s = s;
+ svp->sp = sp;
+ svp->nsp = nsp;
+}
+
+void fillNumberVector(INumberVectorProperty *nvp, INumber *np, int nnp, const char * dev, const char *name, const char *label, const char* group, IPerm p, double timeout, IPState s)
+{
+
+ strcpy(nvp->device, dev);
+ strcpy(nvp->name, name);
+ strcpy(nvp->label, label);
+ strcpy(nvp->group, group);
+ strcpy(nvp->timestamp, "");
+
+ nvp->p = p;
+ nvp->timeout = timeout;
+ nvp->s = s;
+ nvp->np = np;
+ nvp->nnp = nnp;
+
+}
+
+void fillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char * dev, const char *name, const char *label, const char* group, IPerm p, double timeout, IPState s)
+{
+ strcpy(tvp->device, dev);
+ strcpy(tvp->name, name);
+ strcpy(tvp->label, label);
+ strcpy(tvp->group, group);
+ strcpy(tvp->timestamp, "");
+
+ tvp->p = p;
+ tvp->timeout = timeout;
+ tvp->s = s;
+ tvp->tp = tp;
+ tvp->ntp = ntp;
+
+}
+
+/* print usage message and exit (1) */
+static void
+usage(void)
+{
+ fprintf (stderr, "Usage: %s [options]\n", me);
+ fprintf (stderr, "Purpose: INDI Device driver framework.\n");
+ fprintf (stderr, "Options:\n");
+ fprintf (stderr, " -v : more verbose to stderr\n");
+
+ exit (1);
+}
+
+/* callback when INDI client message arrives on stdin.
+ * collect and dispatch when see outter element closure.
+ * exit if OS trouble or see incompatable INDI version.
+ * arg is not used.
+ */
+static void
+clientMsgCB (int fd, void *arg)
+{
+ char buf[1024], msg[1024], *bp;
+ int nr;
+ arg=arg;
+
+ /* one read */
+ nr = read (fd, buf, sizeof(buf));
+ if (nr < 0) {
+ fprintf (stderr, "%s: %s\n", me, strerror(errno));
+ exit(1);
+ }
+ if (nr == 0) {
+ fprintf (stderr, "%s: EOF\n", me);
+ exit(1);
+ }
+
+ /* crack and dispatch when complete */
+ for (bp = buf; nr-- > 0; bp++) {
+ XMLEle *root = readXMLEle (clixml, *bp, msg);
+ if (root) {
+ if (dispatch (root, msg) < 0)
+ fprintf (stderr, "%s dispatch error: %s\n", me, msg);
+ delXMLEle (root);
+ } else if (msg[0])
+ fprintf (stderr, "%s XML error: %s\n", me, msg);
+ }
+}
+
+/* crack the given INDI XML element and call driver's IS* entry points as they
+ * are recognized.
+ * return 0 if ok else -1 with reason in msg[].
+ * N.B. exit if getProperties does not proclaim a compatible version.
+ */
+static int
+dispatch (XMLEle *root, char msg[])
+{
+ XMLEle *epx;
+ int n;
+ int i=0;
+
+ if (verbose)
+ prXMLEle (stderr, root, 0);
+
+ /* check tag in surmised decreasing order of likelyhood */
+
+ if (!strcmp (tagXMLEle(root), "newNumberVector")) {
+ static double *doubles;
+ static char **names;
+ static int maxn;
+ char *dev, *name;
+
+ /* pull out device and name */
+ if (crackDN (root, &dev, &name, msg) < 0)
+ return (-1);
+
+ /* seed for reallocs */
+ if (!doubles) {
+ doubles = (double *) malloc (1);
+ names = (char **) malloc (1);
+ }
+
+ /* pull out each name/value pair */
+ for (n = 0, epx = nextXMLEle(root,1); epx; epx = nextXMLEle(root,0)) {
+ if (strcmp (tagXMLEle(epx), "oneNumber") == 0) {
+ XMLAtt *na = findXMLAtt (epx, "name");
+ if (na) {
+ if (n >= maxn) {
+ /* grow for this and another */
+ int newsz = (maxn=n+1)*sizeof(double);
+ doubles = (double *) realloc(doubles,newsz);
+ newsz = maxn*sizeof(char *);
+ names = (char **) realloc (names, newsz);
+ }
+ if (f_scansexa (pcdataXMLEle(epx), &doubles[n]) < 0)
+ IDMessage (dev,"%s: Bad format %s", name,
+ pcdataXMLEle(epx));
+ else
+ names[n++] = valuXMLAtt(na);
+ }
+ }
+ }
+
+ /* insure property is not RO */
+ for (i=0; i < nroCheck; i++)
+ {
+ if (!strcmp(roCheck[i].propName, name))
+ {
+ if (roCheck[i].perm == IP_RO)
+ return -1;
+ }
+ }
+
+ /* invoke driver if something to do, but not an error if not */
+ if (n > 0)
+ ISNewNumber (dev, name, doubles, names, n);
+ else
+ IDMessage(dev,"%s: newNumberVector with no valid members",name);
+ return (0);
+ }
+
+ if (!strcmp (tagXMLEle(root), "newSwitchVector")) {
+ static ISState *states;
+ static char **names;
+ static int maxn;
+ char *dev, *name;
+
+ /* pull out device and name */
+ if (crackDN (root, &dev, &name, msg) < 0)
+ return (-1);
+
+ /* seed for reallocs */
+ if (!states) {
+ states = (ISState *) malloc (1);
+ names = (char **) malloc (1);
+ }
+
+ /* pull out each name/state pair */
+ for (n = 0, epx = nextXMLEle(root,1); epx; epx = nextXMLEle(root,0)) {
+ if (strcmp (tagXMLEle(epx), "oneSwitch") == 0) {
+ XMLAtt *na = findXMLAtt (epx, "name");
+ if (na) {
+ if (n >= maxn) {
+ int newsz = (maxn=n+1)*sizeof(ISState);
+ states = (ISState *) realloc(states, newsz);
+ newsz = maxn*sizeof(char *);
+ names = (char **) realloc (names, newsz);
+ }
+ if (strcmp (pcdataXMLEle(epx),"On") == 0) {
+ states[n] = ISS_ON;
+ names[n] = valuXMLAtt(na);
+ n++;
+ } else if (strcmp (pcdataXMLEle(epx),"Off") == 0) {
+ states[n] = ISS_OFF;
+ names[n] = valuXMLAtt(na);
+ n++;
+ } else
+ IDMessage (dev, "%s: must be On or Off: %s", name,
+ pcdataXMLEle(epx));
+ }
+ }
+ }
+
+ /* insure property is not RO */
+ for (i=0; i < nroCheck; i++)
+ {
+ if (!strcmp(roCheck[i].propName, name))
+ {
+ if (roCheck[i].perm == IP_RO)
+ return -1;
+ }
+ }
+
+ /* invoke driver if something to do, but not an error if not */
+ if (n > 0)
+ ISNewSwitch (dev, name, states, names, n);
+ else
+ IDMessage(dev,"%s: newSwitchVector with no valid members",name);
+ return (0);
+ }
+
+ if (!strcmp (tagXMLEle(root), "newTextVector")) {
+ static char **texts;
+ static char **names;
+ static int maxn;
+ char *dev, *name;
+
+ /* pull out device and name */
+ if (crackDN (root, &dev, &name, msg) < 0)
+ return (-1);
+
+ /* seed for reallocs */
+ if (!texts) {
+ texts = (char **) malloc (1);
+ names = (char **) malloc (1);
+ }
+
+ /* pull out each name/text pair */
+ for (n = 0, epx = nextXMLEle(root,1); epx; epx = nextXMLEle(root,0)) {
+ if (strcmp (tagXMLEle(epx), "oneText") == 0) {
+ XMLAtt *na = findXMLAtt (epx, "name");
+ if (na) {
+ if (n >= maxn) {
+ int newsz = (maxn=n+1)*sizeof(char *);
+ texts = (char **) realloc (texts, newsz);
+ names = (char **) realloc (names, newsz);
+ }
+ texts[n] = pcdataXMLEle(epx);
+ names[n] = valuXMLAtt(na);
+ n++;
+ }
+ }
+ }
+
+ /* insure property is not RO */
+ for (i=0; i < nroCheck; i++)
+ {
+ if (!strcmp(roCheck[i].propName, name))
+ {
+ if (roCheck[i].perm == IP_RO)
+ return -1;
+ }
+ }
+
+ /* invoke driver if something to do, but not an error if not */
+ if (n > 0)
+ ISNewText (dev, name, texts, names, n);
+ else
+ IDMessage (dev, "%s: set with no valid members", name);
+ return (0);
+ }
+
+ if (!strcmp (tagXMLEle(root), "newBLOBVector")) {
+ static char **blobs;
+ static char **names;
+ static char **formats;
+ static int *sizes;
+ static int maxn;
+ char *dev, *name;
+
+ /* pull out device and name */
+ if (crackDN (root, &dev, &name, msg) < 0)
+ return (-1);
+
+ /* seed for reallocs */
+ if (!blobs) {
+ blobs = (char **) malloc (1);
+ names = (char **) malloc (1);
+ formats = (char **) malloc (1);
+ sizes = (int *) malloc (1);
+ }
+
+ /* pull out each name/BLOB pair */
+ for (n = 0, epx = nextXMLEle(root,1); epx; epx = nextXMLEle(root,0)) {
+ if (strcmp (tagXMLEle(epx), "oneBLOB") == 0) {
+ XMLAtt *na = findXMLAtt (epx, "name");
+ XMLAtt *fa = findXMLAtt (epx, "format");
+ XMLAtt *sa = findXMLAtt (epx, "size");
+ if (na && fa && sa) {
+ if (n >= maxn) {
+ int newsz = (maxn=n+1)*sizeof(char *);
+ blobs = (char **) realloc (blobs, newsz);
+ names = (char **) realloc (names, newsz);
+ formats = (char **) realloc(formats,newsz);
+ newsz = maxn*sizeof(int);
+ sizes = (int *) realloc(sizes,newsz);
+ }
+ blobs[n] = pcdataXMLEle(epx);
+ names[n] = valuXMLAtt(na);
+ formats[n] = valuXMLAtt(fa);
+ sizes[n] = atoi(valuXMLAtt(sa));
+ n++;
+ }
+ }
+ }
+
+ /* invoke driver if something to do, but not an error if not */
+ if (n > 0)
+ ISNewBLOB (dev, name, sizes, blobs, formats, names, n);
+ else
+ IDMessage (dev, "%s: newBLOBVector with no valid members",name);
+ return (0);
+ }
+
+ if (!strcmp (tagXMLEle(root), "getProperties")) {
+ XMLAtt *ap;
+ double v;
+
+ /* check version */
+ ap = findXMLAtt (root, "version");
+ if (!ap) {
+ fprintf (stderr, "%s: getProperties missing version\n", me);
+ exit(1);
+ }
+ v = atof (valuXMLAtt(ap));
+ if (v > INDIV) {
+ fprintf (stderr, "%s: client version %g > %g\n", me, v, INDIV);
+ exit(1);
+ }
+
+ /* ok */
+ ap = findXMLAtt (root, "device");
+ ISGetProperties (ap ? valuXMLAtt(ap) : NULL);
+ return (0);
+ }
+
+ sprintf (msg, "Unknown command: %s", tagXMLEle(root));
+ return(1);
+}
+
+/* pull out device and name attributes from root.
+ * return 0 if ok else -1 with reason in msg[].
+ */
+static int
+crackDN (XMLEle *root, char **dev, char **name, char msg[])
+{
+ XMLAtt *ap;
+
+ ap = findXMLAtt (root, "device");
+ if (!ap) {
+ sprintf (msg, "%s requires 'device' attribute", tagXMLEle(root));
+ return (-1);
+ }
+ *dev = valuXMLAtt(ap);
+
+ ap = findXMLAtt (root, "name");
+ if (!ap) {
+ sprintf (msg, "%s requires 'name' attribute", tagXMLEle(root));
+ return (-1);
+ }
+ *name = valuXMLAtt(ap);
+
+ return (0);
+}
+
+/* return static string corresponding to the given property or light state */
+const char *
+pstateStr (IPState s)
+{
+ switch (s) {
+ case IPS_IDLE: return ("Idle");
+ case IPS_OK: return ("Ok");
+ case IPS_BUSY: return ("Busy");
+ case IPS_ALERT: return ("Alert");
+ default:
+ fprintf (stderr, "Impossible IPState %d\n", s);
+ exit(1);
+ }
+}
+
+/* return static string corresponding to the given switch state */
+const char *
+sstateStr (ISState s)
+{
+ switch (s) {
+ case ISS_ON: return ("On");
+ case ISS_OFF: return ("Off");
+ default:
+ fprintf (stderr, "Impossible ISState %d\n", s);
+ exit(1);
+ }
+}
+
+/* return static string corresponding to the given Rule */
+const char *
+ruleStr (ISRule r)
+{
+ switch (r) {
+ case ISR_1OFMANY: return ("OneOfMany");
+ case ISR_ATMOST1: return ("AtMostOne");
+ case ISR_NOFMANY: return ("AnyOfMany");
+ default:
+ fprintf (stderr, "Impossible ISRule %d\n", r);
+ exit(1);
+ }
+}
+
+/* return static string corresponding to the given IPerm */
+const char *
+permStr (IPerm p)
+{
+ switch (p) {
+ case IP_RO: return ("ro");
+ case IP_WO: return ("wo");
+ case IP_RW: return ("rw");
+ default:
+ fprintf (stderr, "Impossible IPerm %d\n", p);
+ exit(1);
+ }
+}
+
diff --git a/kstars/kstars/indi/indiserver.c b/kstars/kstars/indi/indiserver.c
new file mode 100644
index 00000000..ad4d2ffd
--- /dev/null
+++ b/kstars/kstars/indi/indiserver.c
@@ -0,0 +1,878 @@
+/* INDI Server.
+ * Copyright (C) 2005 Elwood C. Downey ecdowney@clearskyinstitute.com
+ * licensed under GNU Lesser Public License version 2.1 or later.
+ *
+ * argv lists names of Driver programs to run, they are restarted if they exit.
+ * Each Driver's stdin/out are assumed to provide INDI traffic and are connected
+ * here via pipes. Drivers' stderr are connected to our stderr.
+ * Clients can come and go as they please and will see messages only for Devices
+ * for which they have queried via getProperties.
+ * all newXXX() received from one Client are sent to all other Clients who have
+ * shown an interest in the same Device.
+ *
+ * Implementation notes:
+ *
+ * Each Client is written to by its own thread to allow for wildly different
+ * consumption rates. The main thread cracks the xml. When it sees a complete
+ * message it puts it in a new Msg which is the XMLEle and a usage count. The
+ * Msg is put on the q for each eligible Client and the Msg usage count is the
+ * number of Clients on whose q it resides. The Client write thread waits for
+ * a Msg to be on its q, performs the write, decrements the usage count and
+ * frees the Msg (and its XMLEle) if the count reaches 0. This mechanism is
+ * less valuable for Drivers since there is little need to send the same message
+ * to more than one Driver. However, a Driver slow to consume it message can
+ * block us so it still might be worth while for that reason someday.
+ *
+ * All manipulation of the Client info table, clinfo[], is guarded by client_m
+ * and client_c. All heap access is guarded by malloc_m.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include "lilxml.h"
+#include "indiapi.h"
+#include "fq.h"
+
+#define INDIPORT 7624 /* TCP/IP port on which to listen */
+#define BUFSZ 2048 /* max buffering here */
+#define MAXDRS 4 /* default times to restart a driver */
+
+/* mutex and condition variables to guard client queue and heap access */
+static pthread_mutex_t client_m; /* client mutex */
+static pthread_cond_t client_c; /* client condition waiting for Msgs */
+static pthread_mutex_t malloc_m; /* heap mutex */
+
+/* name of a device a client is interested in */
+typedef char IDev[MAXINDIDEVICE]; /* handy array of char */
+
+/* BLOB handling, NEVER is the default */
+typedef enum {B_NEVER=0, B_ALSO, B_ONLY} BLOBEnable;
+
+/* associate a usage count with an XMLEle message */
+typedef struct {
+ XMLEle *ep; /* a message */
+ int count; /* number of consumers left */
+} Msg;
+
+/* info for each connected client */
+typedef struct {
+ int active; /* 1 when this record is in use */
+ int shutdown; /* set to close writer thread */
+ int s; /* socket for this client */
+ FILE *wfp; /* FILE to write to s */
+ BLOBEnable blob; /* when to send setBLOBs */
+ pthread_t wtid; /* writer thread id */
+ LilXML *lp; /* XML parsing context */
+ FQ *msgq; /* Msg queue */
+ IDev *devs; /* malloced array of devices we want */
+ int ndevs; /* n entries in devs[] */
+ int sawGetProperties; /* mark when see getProperties */
+} ClInfo;
+static ClInfo *clinfo; /* malloced array of clients */
+static int nclinfo; /* n total (not n active) */
+
+/* info for each connected driver */
+typedef struct {
+ char *name; /* malloced process path name */
+ IDev dev; /* device served by this driver */
+ int pid; /* process id */
+ int rfd; /* read pipe fd */
+ FILE *wfp; /* write pipe fp */
+ int restarts; /* times process has been restarted */
+ LilXML *lp; /* XML parsing context */
+} DvrInfo;
+static DvrInfo *dvrinfo; /* malloced array of drivers */
+static int ndvrinfo; /* n total */
+
+static void usage (void);
+static void *mymalloc (size_t s);
+static void *myrealloc (void *p, size_t s);
+static void myfree (void *p);
+static void noZombies (void);
+static void noSIGPIPE (void);
+static void indiRun (void);
+static void indiListen (void);
+static void newClient (void);
+static int newClSocket (void);
+static void shutdownClient (ClInfo *cp);
+static void clientMsg (ClInfo *cp);
+static void startDvr (DvrInfo *dp);
+static void restartDvr (DvrInfo *dp);
+static void send2Drivers (XMLEle *root, char *dev);
+static void send2Clients (ClInfo *notme, XMLEle *root, char *dev);
+static void addClDevice (ClInfo *cp, char *dev);
+static int findClDevice (ClInfo *cp, char *dev);
+static void driverMsg (DvrInfo *dp);
+static void *clientWThread(void *carg);
+static void freeMsg (Msg *mp);
+static BLOBEnable crackBLOB (char enableBLOB[]);
+static char *xmlLog (XMLEle *root);
+
+static char *me; /* our name */
+static int port = INDIPORT; /* public INDI port */
+static int verbose; /* more chatty */
+static int maxdrs = MAXDRS; /* max times to restart dieing driver */
+static int lsocket; /* listen socket */
+
+int
+main (int ac, char *av[])
+{
+ /* save our name */
+ me = av[0];
+
+ /* crack args */
+ while ((--ac > 0) && ((*++av)[0] == '-')) {
+ char *s;
+ for (s = av[0]+1; *s != '\0'; s++)
+ switch (*s) {
+ case 'p':
+ if (ac < 2)
+ usage();
+ port = atoi(*++av);
+ ac--;
+ break;
+ case 'r':
+ if (ac < 2)
+ usage();
+ maxdrs = atoi(*++av);
+ ac--;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ /* at this point there are ac args in av[] to name our drivers */
+ if (ac == 0)
+ usage();
+
+ /* take care of some unixisms */
+ noZombies();
+ noSIGPIPE();
+
+ /* init mutexes and condition variables */
+ pthread_mutex_init(&client_m, NULL);
+ pthread_cond_init (&client_c, NULL);
+ pthread_mutex_init(&malloc_m, NULL);
+
+ /* install our locked heap functions */
+ indi_xmlMalloc (mymalloc, myrealloc, myfree);
+ setMemFuncsFQ (mymalloc, myrealloc, myfree);
+
+ /* seed client info array so we can always use realloc */
+ clinfo = (ClInfo *) mymalloc (1);
+ nclinfo = 0;
+
+ /* create driver info array all at once so size never has to change */
+ ndvrinfo = ac;
+ dvrinfo = (DvrInfo *) mymalloc (ndvrinfo * sizeof(DvrInfo));
+ memset (dvrinfo, 0, ndvrinfo * sizeof(DvrInfo));
+
+ /* start each driver, malloc name once and keep it */
+ while (ac-- > 0) {
+ dvrinfo[ac].name = strcpy (mymalloc(strlen(*av)+1), *av);
+ startDvr (&dvrinfo[ac]);
+ av++;
+ }
+
+ /* announce we are online */
+ indiListen();
+
+ /* handle new clients and all reading */
+ while (1)
+ indiRun();
+
+ /* whoa! */
+ fprintf (stderr, "%s: unexpected return from main\n", me);
+ return (1);
+}
+
+/* print usage message and exit (1) */
+static void
+usage(void)
+{
+ fprintf (stderr, "Usage: %s [options] driver [driver ...]\n", me);
+ fprintf (stderr, "%s\n", "$Revision$");
+ fprintf (stderr, "Purpose: INDI Server\n");
+ fprintf (stderr, "Options:\n");
+ fprintf (stderr, " -p p : alternate IP port, default %d\n", INDIPORT);
+ fprintf (stderr, " -r n : max driver restarts, default %d\n", MAXDRS);
+ fprintf (stderr, " -v : show connects/disconnects, no traffic\n");
+ fprintf (stderr, " -vv : show -v + xml message root elements\n");
+ fprintf (stderr, " -vvv : show -vv + complete xml messages\n");
+
+ exit (1);
+}
+
+/* like malloc(3) but honors malloc_m mutex lock */
+static void *
+mymalloc (size_t s)
+{
+ void *mem;
+
+ pthread_mutex_lock (&malloc_m);
+ mem = malloc (s);
+ pthread_mutex_unlock (&malloc_m);
+ return (mem);
+}
+
+/* like realloc(3) but honors malloc_m mutex lock */
+static void *
+myrealloc (void *p, size_t s)
+{
+ void *mem;
+
+ pthread_mutex_lock (&malloc_m);
+ mem = realloc (p, s);
+ pthread_mutex_unlock (&malloc_m);
+ return (mem);
+}
+
+/* like free(3) but honors malloc_m mutex lock */
+static void
+myfree (void *p)
+{
+ pthread_mutex_lock (&malloc_m);
+ free (p);
+ pthread_mutex_unlock (&malloc_m);
+}
+
+/* arrange for no zombies if drivers die */
+static void
+noZombies()
+{
+ struct sigaction sa;
+ sa.sa_handler = SIG_IGN;
+ sigemptyset(&sa.sa_mask);
+#ifdef SA_NOCLDWAIT
+ sa.sa_flags = SA_NOCLDWAIT;
+#else
+ sa.sa_flags = 0;
+#endif
+ (void)sigaction(SIGCHLD, &sa, NULL);
+}
+
+/* turn off SIGPIPE on bad write so we can handle it inline */
+static void
+noSIGPIPE()
+{
+ struct sigaction sa;
+ sa.sa_handler = SIG_IGN;
+ sigemptyset(&sa.sa_mask);
+ (void)sigaction(SIGPIPE, &sa, NULL);
+}
+
+/* start the INDI driver process using the given DvrInfo slot.
+ * exit if trouble.
+ */
+static void
+startDvr (DvrInfo *dp)
+{
+ int rp[2], wp[2];
+ int pid;
+
+ /* build two pipes for r and w */
+ if (pipe (rp) < 0) {
+ fprintf (stderr, "%s: read pipe: %s\n", me, strerror(errno));
+ exit(1);
+ }
+ if (pipe (wp) < 0) {
+ fprintf (stderr, "%s: write pipe: %s\n", me, strerror(errno));
+ exit(1);
+ }
+
+ /* fork&exec new process */
+ pid = fork();
+ if (pid < 0) {
+ fprintf (stderr, "%s: fork: %s\n", me, strerror(errno));
+ exit(1);
+ }
+ if (pid == 0) {
+ /* child: exec name */
+ int fd;
+
+ /* rig up pipes as stdin/out; stderr stays, everything else goes */
+ dup2 (wp[0], 0);
+ dup2 (rp[1], 1);
+ for (fd = 3; fd < 100; fd++)
+ (void) close (fd);
+
+ /* go -- should never return */
+ execlp (dp->name, dp->name, NULL);
+ fprintf (stderr, "Driver %s: %s\n", dp->name, strerror(errno));
+ _exit (1); /* parent will notice EOF shortly */
+ }
+
+ /* don't need child's side of pipes */
+ close (rp[1]);
+ close (wp[0]);
+
+ /* record pid, io channel, init lp */
+ dp->pid = pid;
+ dp->rfd = rp[0];
+ dp->lp = newLilXML();
+
+ /* N.B. beware implied use of malloc */
+ pthread_mutex_lock (&malloc_m);
+ dp->wfp = fdopen (wp[1], "a");
+ setbuf (dp->wfp, NULL);
+ pthread_mutex_unlock (&malloc_m);
+
+ if (verbose > 0)
+ fprintf (stderr, "Driver %s: rfd=%d wfd=%d\n", dp->name, dp->rfd,
+ wp[1]);
+}
+
+/* create the public INDI Driver endpoint lsocket on port.
+ * return server socket else exit.
+ */
+static void
+indiListen ()
+{
+ struct sockaddr_in serv_socket;
+ int sfd;
+ int reuse = 1;
+
+ /* make socket endpoint */
+ if ((sfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
+ fprintf (stderr, "%s: socket: %s", me, strerror(errno));
+ exit(1);
+ }
+
+ /* bind to given port for local IP addresses only */
+ memset (&serv_socket, 0, sizeof(serv_socket));
+ serv_socket.sin_family = AF_INET;
+ serv_socket.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ serv_socket.sin_port = htons ((unsigned short)port);
+ if (setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0){
+ fprintf (stderr, "%s: setsockopt: %s", me, strerror(errno));
+ exit(1);
+ }
+ if (bind(sfd,(struct sockaddr*)&serv_socket,sizeof(serv_socket)) < 0){
+ fprintf (stderr, "%s: bind: %s", me, strerror(errno));
+ exit(1);
+ }
+
+ /* willing to accept connections with a backlog of 5 pending */
+ if (listen (sfd, 5) < 0) {
+ fprintf (stderr, "%s: listen: %s", me, strerror(errno));
+ exit(1);
+ }
+
+ /* ok */
+ lsocket = sfd;
+ if (verbose > 0)
+ fprintf (stderr, "%s: listening to port %d on fd %d\n",me,port,sfd);
+}
+
+/* service traffic from clients and drivers */
+static void
+indiRun(void)
+{
+ fd_set rs;
+ int maxfd;
+ int i, s;
+
+ /* start with public contact point */
+ FD_ZERO(&rs);
+ FD_SET(lsocket, &rs);
+ maxfd = lsocket;
+
+ /* add all client and driver read fd's */
+ for (i = 0; i < nclinfo; i++) {
+ ClInfo *cp = &clinfo[i];
+ if (cp->active) {
+ FD_SET(cp->s, &rs);
+ if (cp->s > maxfd)
+ maxfd = cp->s;
+ }
+ }
+ for (i = 0; i < ndvrinfo; i++) {
+ DvrInfo *dp = &dvrinfo[i];
+ FD_SET(dp->rfd, &rs);
+ if (dp->rfd > maxfd)
+ maxfd = dp->rfd;
+ }
+
+ /* wait for action */
+ s = select (maxfd+1, &rs, NULL, NULL, NULL);
+ if (s < 0) {
+ fprintf (stderr, "%s: select(%d): %s\n",me,maxfd+1,strerror(errno));
+ exit(1);
+ }
+
+ /* new client? */
+ if (s > 0 && FD_ISSET(lsocket, &rs)) {
+ newClient();
+ s -= 1;
+ }
+
+ /* message from client? */
+ for (i = 0; s > 0 && i < nclinfo; i++) {
+ if (clinfo[i].active && FD_ISSET(clinfo[i].s, &rs)) {
+ clientMsg(&clinfo[i]);
+ s -= 1;
+ }
+ }
+
+ /* message from driver? */
+ for (i = 0; s > 0 && i < ndvrinfo; i++) {
+ if (FD_ISSET(dvrinfo[i].rfd, &rs)) {
+ driverMsg(&dvrinfo[i]);
+ s -= 1;
+ }
+ }
+}
+
+/* prepare for new client arriving on lsocket.
+ * exit if trouble.
+ */
+static void
+newClient()
+{
+ ClInfo *cp = NULL;
+ int s, cli;
+
+ /* assign new socket */
+ s = newClSocket ();
+
+ /* try to reuse a clinfo slot, else add one */
+ for (cli = 0; cli < nclinfo; cli++)
+ if (!(cp = &clinfo[cli])->active)
+ break;
+ if (cli == nclinfo) {
+ /* grow clinfo, lock while moving */
+ pthread_mutex_lock (&client_m);
+ clinfo = (ClInfo *) myrealloc (clinfo, (nclinfo+1)*sizeof(ClInfo));
+ if (!clinfo) {
+ fprintf (stderr, "%s: no memory for new client\n", me);
+ exit(1);
+ }
+ cp = &clinfo[nclinfo++];
+ pthread_mutex_unlock (&client_m);
+ }
+
+ /* rig up new clinfo entry */
+ memset (cp, 0, sizeof(*cp));
+ cp->active = 1;
+ cp->s = s;
+ cp->lp = newLilXML();
+ cp->msgq = newFQ(1);
+ cp->devs = mymalloc (1);
+
+ /* N.B. beware implied use of malloc */
+ pthread_mutex_lock (&malloc_m);
+ cp->wfp = fdopen (cp->s, "a");
+ setbuf (cp->wfp, NULL);
+ pthread_mutex_unlock (&malloc_m);
+
+ if (verbose > 0)
+ fprintf (stderr, "Client %d: new arrival - welcome!\n", cp->s);
+
+ /* start the writer thread */
+ s = pthread_create (&cp->wtid, NULL, clientWThread, (void*)(cp-clinfo));
+ if (s) {
+ fprintf (stderr, "Thread create error: %s\n", strerror(s));
+ exit (1);
+ }
+}
+
+/* read more from the given client, send to each appropriate driver when see
+ * xml closure. also send all newXXX() to all other interested clients.
+ * shut down client if any trouble.
+ */
+static void
+clientMsg (ClInfo *cp)
+{
+ char buf[BUFSZ];
+ int i, nr;
+
+ /* read client */
+ nr = read (cp->s, buf, sizeof(buf));
+ if (nr < 0) {
+ fprintf (stderr, "Client %d: %s\n", cp->s, strerror(errno));
+ shutdownClient (cp);
+ return;
+ }
+ if (nr == 0) {
+ if (verbose)
+ fprintf (stderr, "Client %d: read EOF\n", cp->s);
+ shutdownClient (cp);
+ return;
+ }
+ if (verbose > 2)
+ fprintf (stderr, "Client %d: read %d:\n%.*s", cp->s, nr, nr, buf);
+
+ /* process XML, sending when find closure */
+ for (i = 0; i < nr; i++) {
+ char err[1024];
+ XMLEle *root = readXMLEle (cp->lp, buf[i], err);
+ if (root) {
+ char *roottag = tagXMLEle(root);
+
+ if (verbose > 1)
+ fprintf (stderr, "Client %d: read %s\n", cp->s,
+ xmlLog(root));
+
+ /* record BLOB message locally, others go to matching drivers */
+ if (!strcmp (roottag, "enableBLOB")) {
+ cp->blob = crackBLOB (pcdataXMLEle(root));
+ delXMLEle (root);
+ } else {
+ char *dev = findXMLAttValu (root, "device");
+
+ /* snag interested devices */
+ if (!strcmp (roottag, "getProperties"))
+ addClDevice (cp, dev);
+
+ /* send message to driver(s) responsible for dev */
+ send2Drivers (root, dev);
+
+ /* echo new* commands back to other clients, else done */
+ if (!strncmp (roottag, "new", 3))
+ send2Clients (cp, root, dev); /* does delXMLEle */
+ else
+ delXMLEle (root);
+ }
+ } else if (err[0])
+ fprintf (stderr, "Client %d: %s\n", cp->s, err);
+ }
+}
+
+/* read more from the given driver, send to each interested client when see
+ * xml closure. if driver dies, try to restarting up to MAXDRS times.
+ */
+static void
+driverMsg (DvrInfo *dp)
+{
+ char buf[BUFSZ];
+ int i, nr;
+
+ /* read driver */
+ nr = read (dp->rfd, buf, sizeof(buf));
+ if (nr < 0) {
+ fprintf (stderr, "Driver %s: %s\n", dp->name, strerror(errno));
+ restartDvr (dp);
+ return;
+ }
+ if (nr == 0) {
+ fprintf (stderr, "Driver %s: died, or failed to start\n", dp->name);
+ restartDvr (dp);
+ return;
+ }
+ if (verbose > 2)
+ fprintf (stderr,"Driver %s: read %d:\n%.*s", dp->name, nr, nr, buf);
+
+ /* process XML, sending when find closure */
+ for (i = 0; i < nr; i++) {
+ char err[1024];
+ XMLEle *root = readXMLEle (dp->lp, buf[i], err);
+ if (root) {
+ char *dev = findXMLAttValu(root,"device");
+
+ if (verbose > 1)
+ fprintf(stderr,"Driver %s: read %s\n",dp->name,xmlLog(root));
+
+ /* snag device name if not known yet */
+ if (!dp->dev[0] && dev[0]) {
+ strncpy (dp->dev, dev, sizeof(IDev)-1);
+ dp->dev[sizeof(IDev)-1] = '\0';
+ }
+
+ /* send to interested clients */
+ send2Clients (NULL, root, dev);
+ } else if (err[0])
+ fprintf (stderr, "Driver %s: %s\n", dp->name, err);
+ }
+}
+
+/* close down the given client */
+static void
+shutdownClient (ClInfo *cp)
+{
+ /* inform writer thread to exit then wait for it */
+ cp->shutdown = 1;
+ pthread_cond_broadcast (&client_c);
+ pthread_join (cp->wtid, NULL);
+
+ /* recycle this clinfo cell */
+ cp->active = 0;
+
+ if (verbose > 0)
+ fprintf (stderr, "Client %d: closed\n", cp->s);
+}
+
+/* close down the given driver and restart if not too many already */
+static void
+restartDvr (DvrInfo *dp)
+{
+ /* make sure it's dead, reclaim resources */
+ kill (dp->pid, SIGKILL);
+ fclose (dp->wfp);
+ close (dp->rfd);
+ delLilXML (dp->lp);
+
+ /* restart unless too many already */
+ if (++dp->restarts > maxdrs) {
+ fprintf (stderr, "Driver %s: died after %d restarts\n", dp->name,
+ maxdrs);
+ exit(1);
+ }
+ fprintf (stderr, "Driver %s: restart #%d\n", dp->name, dp->restarts);
+ startDvr (dp);
+}
+
+/* send the xml command to each driver supporting device dev, or all if unknown.
+ * restart if write fails.
+ */
+static void
+send2Drivers (XMLEle *root, char *dev)
+{
+ int i;
+
+ for (i = 0; i < ndvrinfo; i++) {
+ DvrInfo *dp = &dvrinfo[i];
+ if (dev[0] && dp->dev[0] && strcmp (dev, dp->dev))
+ continue;
+ prXMLEle (dp->wfp, root, 0);
+ if (ferror(dp->wfp)) {
+ fprintf (stderr, "Driver %s: %s\n", dp->name, strerror(errno));
+ restartDvr (dp);
+ } else if (verbose > 2) {
+ fprintf (stderr, "Driver %s: send:\n", dp->name);
+ prXMLEle (stderr, root, 0);
+ } else if (verbose > 1)
+ fprintf(stderr,"Driver %s: send %s\n", dp->name, xmlLog(root));
+ }
+}
+
+/* queue the xml command in root from the given device to each
+ * interested client, except notme
+ */
+static void
+send2Clients (ClInfo *notme, XMLEle *root, char *dev)
+{
+ ClInfo *cp;
+ Msg *mp;
+
+ /* build a new message */
+ mp = (Msg *) mymalloc (sizeof(Msg));
+ mp->ep = root;
+ mp->count = 0;
+
+ /* lock access to client info */
+ pthread_mutex_lock (&client_m);
+
+ /* queue message to each interested client */
+ for (cp = clinfo; cp < &clinfo[nclinfo]; cp++) {
+ int isblob;
+
+ /* cp ok? notme? valid dev? blob? */
+ if (!cp->active || cp == notme)
+ continue;
+ if (findClDevice (cp, dev) < 0)
+ continue;
+ isblob = !strcmp (tagXMLEle(root), "setBLOBVector");
+ if ((isblob && cp->blob==B_NEVER) || (!isblob && cp->blob==B_ONLY))
+ continue;
+
+ /* ok: queue message to given client */
+ mp->count++;
+ pushFQ (cp->msgq, mp);
+ }
+
+ /* wake up client write threads, the last of which will free the Msg */
+ if (mp->count > 0)
+ pthread_cond_broadcast(&client_c);
+ else {
+ if (verbose > 2)
+ fprintf (stderr, "no clients want %s\n", xmlLog(root));
+ freeMsg (mp); /* no interested clients, free Msg now */
+ }
+
+ /* finished with client info */
+ pthread_mutex_unlock (&client_m);
+}
+
+/* free Msg mp and everything it contains */
+static void
+freeMsg (Msg *mp)
+{
+ delXMLEle (mp->ep);
+ myfree (mp);
+}
+
+/* this function is the thread to perform all writes to client carg.
+ * return with client closed when we have problems or when shutdown flag is set.
+ * N.B. coordinate all access to clinfo via client_m/c.
+ * N.B. clinfo can move (be realloced) when unlocked so beware pointers thereto.
+ */
+static void *
+clientWThread(void *carg)
+{
+ int c = (int)carg;
+ ClInfo *cp;
+ Msg *mp;
+
+ /* start off wanting exclusive access to client info */
+ pthread_mutex_lock (&client_m);
+
+ /* loop until told to shut down or get write error */
+ while (1) {
+
+ /* check for message or shutdown, unlock while waiting */
+ while (nFQ(clinfo[c].msgq) == 0 && !clinfo[c].shutdown) {
+ if (verbose > 2)
+ fprintf (stderr,"Client %d: thread sleeping\n",clinfo[c].s);
+ pthread_cond_wait (&client_c, &client_m);
+ if (verbose > 2)
+ fprintf (stderr, "Client %d: thread awake\n", clinfo[c].s);
+ }
+ if (clinfo[c].shutdown)
+ break;
+
+ /* get next message for this client */
+ mp = popFQ (clinfo[c].msgq);
+
+ /* unlock client info while writing */
+ pthread_mutex_unlock (&client_m);
+ prXMLEle (clinfo[c].wfp, mp->ep, 0);
+ pthread_mutex_lock (&client_m);
+
+ /* trace */
+ cp = &clinfo[c]; /* ok to use pointer while locked */
+ if (verbose > 2) {
+ fprintf (stderr, "Client %d: send:\n", cp->s);
+ prXMLEle (stderr, mp->ep, 0);
+ } else if (verbose > 1)
+ fprintf (stderr, "Client %d: send %s\n", cp->s, xmlLog(mp->ep));
+
+ /* update message usage count, free if goes to 0 */
+ if (--mp->count == 0)
+ freeMsg (mp);
+
+ /* exit this thread if encountered write errors */
+ if (ferror(cp->wfp)) {
+ fprintf (stderr, "Client %d: %s\n", cp->s, strerror(errno));
+ break;
+ }
+ }
+
+ /* close down this client */
+ cp = &clinfo[c]; /* ok to use pointer while locked */
+ fclose (cp->wfp); /* also closes cp->s */
+ delLilXML (cp->lp);
+ myfree (cp->devs);
+
+ /* decrement and possibly free any unsent messages for this client */
+ while ((mp = (Msg*) popFQ(cp->msgq)) != NULL)
+ if (--mp->count == 0)
+ freeMsg (mp);
+ delFQ (cp->msgq);
+
+ /* this thread is now finished with client info */
+ pthread_mutex_unlock (&client_m);
+
+ /* exit thread */
+ return (0);
+}
+
+/* return 0 if we have seen getProperties from this client and dev is in its
+ * devs[] list or the list is empty, else return -1
+ */
+static int
+findClDevice (ClInfo *cp, char *dev)
+{
+ int i;
+
+ if (!cp->sawGetProperties)
+ return (-1);
+ if (cp->ndevs == 0)
+ return (0);
+ for (i = 0; i < cp->ndevs; i++)
+ if (!strncmp (dev, cp->devs[i], sizeof(IDev)-1))
+ return (0);
+ return (-1);
+}
+
+/* add the given device to the devs[] list of client cp unless empty.
+ * regardless, record having seen getProperties from this client.
+ */
+static void
+addClDevice (ClInfo *cp, char *dev)
+{
+
+ if (dev[0]) {
+ char *ip;
+ cp->devs = (IDev *) myrealloc (cp->devs,(cp->ndevs+1)*sizeof(IDev));
+ ip = (char*)&cp->devs[cp->ndevs++];
+ strncpy (ip, dev, sizeof(IDev)-1);
+ ip[sizeof(IDev)-1] = '\0';
+ }
+
+ cp->sawGetProperties = 1;
+}
+
+
+/* block to accept a new client arriving on lsocket.
+ * return private nonblocking socket or exit.
+ */
+static int
+newClSocket ()
+{
+ struct sockaddr_in cli_socket;
+ int cli_len, cli_fd;
+
+ /* get a private connection to new client */
+ cli_len = sizeof(cli_socket);
+ cli_fd = accept (lsocket, (struct sockaddr *)&cli_socket, &cli_len);
+ if(cli_fd < 0) {
+ fprintf (stderr, "%s: accept: %s", me, strerror(errno));
+ exit (1);
+ }
+
+ /* ok */
+ return (cli_fd);
+}
+
+/* convert the string value of enableBLOB to our state value */
+static BLOBEnable
+crackBLOB (char enableBLOB[])
+{
+ if (!strcmp (enableBLOB, "Also"))
+ return (B_ALSO);
+ if (!strcmp (enableBLOB, "Only"))
+ return (B_ONLY);
+ return (B_NEVER);
+}
+
+/* return pointer to static string containing tag, device and name attributes
+ * of the given xml
+ */
+static char *
+xmlLog (XMLEle *root)
+{
+ static char buf[256];
+
+ sprintf (buf, "%.*s %.*s %.*s",
+ sizeof(buf)/3-2, tagXMLEle(root),
+ sizeof(buf)/3-2, findXMLAttValu(root,"device"),
+ sizeof(buf)/3-2, findXMLAttValu(root,"name"));
+ return (buf);
+}
diff --git a/kstars/kstars/indi/lilxml.c b/kstars/kstars/indi/lilxml.c
new file mode 100644
index 00000000..c8344b5e
--- /dev/null
+++ b/kstars/kstars/indi/lilxml.c
@@ -0,0 +1,762 @@
+#if 0
+ liblilxml
+ Copyright (C) 2003 Elwood C. Downey
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+/* little DOM-style XML parser.
+ * only handles elements, attributes and pcdata content.
+ * <! ... > and <? ... > are silently ignored.
+ * pcdata is collected into one string, sans leading whitespace first line.
+ *
+ * #define MAIN_TST to create standalone test program
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "lilxml.h"
+#include "indicom.h"
+
+static int oneXMLchar (LilXML *lp, int c, char errmsg[]);
+static void initParser(LilXML *lp);
+static void pushXMLEle(LilXML *lp);
+static void popXMLEle(LilXML *lp);
+static void resetEndTag(LilXML *lp);
+static void addAttr(LilXML *lp);
+static void delAttr (XMLAtt *a);
+static int isTokenChar (int start, int c);
+static void growString (char **sp, int c);
+static void growPCData (XMLEle *ep, int c);
+static char *newString (void);
+static void *moremem (void *old, int n);
+static void freemem (void *m);
+
+typedef enum {
+ LOOK4START = 0, /* looking for first element start */
+ LOOK4TAG, /* looking for element tag */
+ INTAG, /* reading tag */
+ LOOK4ATTRN, /* looking for attr name, > or / */
+ INATTRN, /* reading attr name */
+ LOOK4ATTRV, /* looking for attr value */
+ SAWSLASH, /* saw / in element opening */
+ INATTRV, /* in attr value */
+ LOOK4CON, /* skipping leading content whitespc */
+ INCON, /* reading content */
+ LTINCON, /* saw < in content */
+ LOOK4CLOSETAG, /* looking for closing tag after < */
+ INCLOSETAG /* reading closing tag */
+} State; /* parsing states */
+
+/* maintain state while parsing */
+struct _LilXML {
+ State cs; /* current state */
+ int ln; /* line number for diags */
+ XMLEle *ce; /* current element being built */
+ char *endtag; /* to check for match with opening tag*/
+ int delim; /* attribute value delimiter */
+ int lastc; /* last char (just used wiht skipping)*/
+ int skipping; /* in comment or declaration */
+};
+
+/* internal representation of a (possibly nested) XML element */
+struct _xml_ele {
+ char *tag; /* element tag */
+ struct _xml_ele *pe; /* parent element, or NULL if root */
+ XMLAtt **at; /* list of attributes */
+ int nat; /* number of attributes */
+ int ait; /* used to iterate over at[] */
+ struct _xml_ele **el; /* list of child elements */
+ int nel; /* number of child elements */
+ int eit; /* used to iterate over el[] */
+ char *pcdata; /* character data in this element */
+ int pcdatal; /* handy length sans \0 (tends to be big) */
+};
+
+/* internal representation of an attribute */
+struct _xml_att {
+ char *name; /* name */
+ char *valu; /* value */
+ struct _xml_ele *ce; /* containing element */
+};
+
+/* default memory managers, override with indi_xmlMalloc() */
+static void *(*mymalloc)(size_t size) = malloc;
+static void *(*myrealloc)(void *ptr, size_t size) = realloc;
+static void (*myfree)(void *ptr) = free;
+
+/* install new version of malloc/realloc/free.
+ * N.B. don't call after first use of any other lilxml function
+ */
+void
+indi_xmlMalloc (void *(*newmalloc)(size_t size),
+ void *(*newrealloc)(void *ptr, size_t size),
+ void (*newfree)(void *ptr))
+{
+ mymalloc = newmalloc;
+ myrealloc = newrealloc;
+ myfree = newfree;
+}
+
+/* pass back a fresh handle for use with our other functions */
+LilXML *
+newLilXML ()
+{
+ LilXML *lp = (LilXML *) moremem (NULL, sizeof(LilXML));
+ initParser(lp);
+ return (lp);
+}
+
+/* discard */
+void
+delLilXML (LilXML *lp)
+{
+ freemem (lp);
+}
+
+/* delete ep and all its children */
+void
+delXMLEle (XMLEle *ep)
+{
+ int i;
+
+ /* benign if NULL */
+ if (!ep)
+ return;
+
+ /* delete all parts of ep */
+ freemem (ep->tag);
+ freemem (ep->pcdata);
+ if (ep->at) {
+ for (i = 0; i < ep->nat; i++)
+ delAttr (ep->at[i]);
+ freemem (ep->at);
+ }
+ if (ep->el) {
+ for (i = 0; i < ep->nel; i++)
+ delXMLEle (ep->el[i]);
+ freemem (ep->el);
+ }
+
+ /* delete ep itself */
+ freemem (ep);
+}
+
+/* process one more character of an XML file.
+ * when find closure with outter element return root of complete tree.
+ * when find error return NULL with reason in errmsg[].
+ * when need more return NULL with errmsg[0] = '\0'.
+ * N.B. it is up to the caller to delete the tree delXMLEle().
+ */
+XMLEle *
+readXMLEle (LilXML *lp, int newc, char errmsg[])
+{
+ XMLEle *root;
+ int s;
+
+ /* start optimistic */
+ errmsg[0] = '\0';
+
+ /* EOF? */
+ if (newc == 0) {
+ snprintf (errmsg, ERRMSG_SIZE, "Line %d: XML EOF", lp->ln);
+ initParser(lp);
+ return (NULL);
+ }
+
+ /* new line? */
+ if (newc == '\n')
+ lp->ln++;
+
+ /* skip comments and declarations. requires 1 char history */
+ if (!lp->skipping && lp->lastc == '<' && (newc == '?' || newc == '!')) {
+ lp->skipping = 1;
+ lp->lastc = newc;
+ return (NULL);
+ }
+ if (lp->skipping) {
+ if (newc == '>')
+ lp->skipping = 0;
+ lp->lastc = newc;
+ return (NULL);
+ }
+ if (newc == '<') {
+ lp->lastc = '<';
+ return (NULL);
+ }
+
+ /* do a pending '<' first then newc */
+ if (lp->lastc == '<') {
+ if (oneXMLchar (lp, '<', errmsg) < 0) {
+ initParser(lp);
+ return (NULL);
+ }
+ /* N.B. we assume '<' will never result in closure */
+ }
+
+ /* process newc (at last!) */
+ s = oneXMLchar (lp, newc, errmsg);
+ if (s == 0) {
+ lp->lastc = newc;
+ return (NULL);
+ }
+ if (s < 0) {
+ initParser(lp);
+ return (NULL);
+ }
+
+ /* Ok! return ce and we start over.
+ * N.B. up to caller to call delXMLEle with what we return.
+ */
+ root = lp->ce;
+ lp->ce = NULL;
+ initParser(lp);
+ return (root);
+}
+
+/* search ep for an attribute with given name.
+ * return NULL if not found.
+ */
+XMLAtt *
+findXMLAtt (XMLEle *ep, const char *name)
+{
+ int i;
+
+ for (i = 0; i < ep->nat; i++)
+ if (!strcmp (ep->at[i]->name, name))
+ return (ep->at[i]);
+ return (NULL);
+}
+
+/* search ep for an element with given tag.
+ * return NULL if not found.
+ */
+XMLEle *
+findXMLEle (XMLEle *ep, const char *tag)
+{
+ int i;
+
+ for (i = 0; i < ep->nel; i++)
+ if (!strcmp (ep->el[i]->tag, tag))
+ return (ep->el[i]);
+ return (NULL);
+}
+
+/* iterate over each child element of ep.
+ * call first time with first set to 1, then 0 from then on.
+ * returns NULL when no more or err
+ */
+XMLEle *
+nextXMLEle (XMLEle *ep, int init)
+{
+ int eit;
+
+ if (init)
+ ep->eit = 0;
+
+ eit = ep->eit++;
+ if (eit < 0 || eit >= ep->nel)
+ return (NULL);
+ return (ep->el[eit]);
+}
+
+/* iterate over each attribute of ep.
+ * call first time with first set to 1, then 0 from then on.
+ * returns NULL when no more or err
+ */
+XMLAtt *
+nextXMLAtt (XMLEle *ep, int init)
+{
+ int ait;
+
+ if (init)
+ ep->ait = 0;
+
+ ait = ep->ait++;
+ if (ait < 0 || ait >= ep->nat)
+ return (NULL);
+ return (ep->at[ait]);
+}
+
+/* return parent of given XMLEle */
+XMLEle *
+parentXMLEle (XMLEle *ep)
+{
+ return (ep->pe);
+}
+
+/* return parent element of given XMLAtt */
+XMLEle *
+parentXMLAtt (XMLAtt *ap)
+{
+ return (ap->ce);
+}
+
+/* access functions */
+
+/* return the tag name of the given element */
+char *
+tagXMLEle (XMLEle *ep)
+{
+ return (ep->tag);
+}
+
+/* return the pcdata portion of the given element */
+char *
+pcdataXMLEle (XMLEle *ep)
+{
+ return (ep->pcdata);
+}
+
+/* return the number of characters in the pcdata portion of the given element */
+int
+pcdatalenXMLEle (XMLEle *ep)
+{
+ return (ep->pcdatal);
+}
+
+/* return the nanme of the given attribute */
+char *
+nameXMLAtt (XMLAtt *ap)
+{
+ return (ap->name);
+}
+
+/* return the value of the given attribute */
+char *
+valuXMLAtt (XMLAtt *ap)
+{
+ return (ap->valu);
+}
+
+/* return the number of child elements of the given element */
+int
+nXMLEle (XMLEle *ep)
+{
+ return (ep->nel);
+}
+
+/* return the number of attributes in the given element */
+int
+nXMLAtt (XMLEle *ep)
+{
+ return (ep->nat);
+}
+
+
+/* search ep for an attribute with the given name and return its value.
+ * return "" if not found.
+ */
+const char *
+findXMLAttValu (XMLEle *ep, char *name)
+{
+ XMLAtt *a = findXMLAtt (ep, name);
+ return (a ? a->valu : "");
+}
+
+/* handy wrapper to read one xml file.
+ * return root element else NULL with report in errmsg[]
+ */
+XMLEle *
+readXMLFile (FILE *fp, LilXML *lp, char errmsg[])
+{
+ int c;
+
+ while ((c = fgetc(fp)) != EOF) {
+ XMLEle *root = readXMLEle (lp, c, errmsg);
+ if (root || errmsg[0])
+ return (root);
+ }
+
+ return (NULL);
+}
+
+/* sample print ep to fp
+ * N.B. set level = 0 on first call
+ */
+#define PRINDENT 4 /* sample print indent each level */
+void
+prXMLEle (FILE *fp, XMLEle *ep, int level)
+{
+ int indent = level*PRINDENT;
+ int i;
+
+ fprintf (fp, "%*s<%s", indent, "", ep->tag);
+ for (i = 0; i < ep->nat; i++)
+ fprintf (fp, " %s=\"%s\"", ep->at[i]->name, ep->at[i]->valu);
+ if (ep->nel > 0) {
+ fprintf (fp, ">\n");
+ for (i = 0; i < ep->nel; i++)
+ prXMLEle (fp, ep->el[i], level+1);
+ }
+ if (ep->pcdata[0]) {
+ char *nl;
+ if (ep->nel == 0)
+ fprintf (fp, ">\n");
+ /* indent if none or one line */
+ nl = strpbrk (ep->pcdata, "\n\r");
+ if (!nl || nl == &ep->pcdata[ep->pcdatal-1])
+ fprintf (fp, "%*s", indent+PRINDENT, "");
+ fprintf (fp, "%s", ep->pcdata);
+ if (!nl)
+ fprintf (fp, "\n");
+ }
+ if (ep->nel > 0 || ep->pcdata[0])
+ fprintf (fp, "%*s</%s>\n", indent, "", ep->tag);
+ else
+ fprintf (fp, "/>\n");
+}
+
+
+
+/* process one more char in XML file.
+ * if find final closure, return 1 and tree is in ce.
+ * if need more, return 0.
+ * if real trouble, return -1 and put reason in errmsg.
+ */
+static int
+oneXMLchar (LilXML *lp, int c, char errmsg[])
+{
+ switch (lp->cs) {
+ case LOOK4START: /* looking for first element start */
+ if (c == '<') {
+ pushXMLEle(lp);
+ lp->cs = LOOK4TAG;
+ }
+ /* silently ignore until resync */
+ break;
+
+ case LOOK4TAG: /* looking for element tag */
+ if (isTokenChar (1, c)) {
+ growString (&lp->ce->tag, c);
+ lp->cs = INTAG;
+ } else if (!isspace(c)) {
+ snprintf (errmsg, ERRMSG_SIZE, "Line %d: Bogus tag char %c", lp->ln, c);
+ return (-1);
+ }
+ break;
+
+ case INTAG: /* reading tag */
+ if (isTokenChar (0, c))
+ growString (&lp->ce->tag, c);
+ else if (c == '>')
+ lp->cs = LOOK4CON;
+ else if (c == '/')
+ lp->cs = SAWSLASH;
+ else
+ lp->cs = LOOK4ATTRN;
+ break;
+
+ case LOOK4ATTRN: /* looking for attr name, > or / */
+ if (c == '>')
+ lp->cs = LOOK4CON;
+ else if (c == '/')
+ lp->cs = SAWSLASH;
+ else if (isTokenChar (1, c)) {
+ addAttr(lp);
+ growString (&lp->ce->at[lp->ce->nat-1]->name, c);
+ lp->cs = INATTRN;
+ } else if (!isspace(c)) {
+ snprintf (errmsg, ERRMSG_SIZE, "Line %d: Bogus leading attr name char: %c",
+ lp->ln, c);
+ return (-1);
+ }
+ break;
+
+ case SAWSLASH: /* saw / in element opening */
+ if (c == '>') {
+ if (!lp->ce->pe)
+ return(1); /* root has no content */
+ popXMLEle(lp);
+ lp->cs = LOOK4CON;
+ } else {
+ snprintf (errmsg, ERRMSG_SIZE, "Line %d: Bogus char %c before >", lp->ln, c);
+ return (-1);
+ }
+ break;
+
+ case INATTRN: /* reading attr name */
+ if (isTokenChar (0, c))
+ growString (&lp->ce->at[lp->ce->nat-1]->name, c);
+ else if (isspace(c) || c == '=')
+ lp->cs = LOOK4ATTRV;
+ else {
+ snprintf (errmsg, ERRMSG_SIZE, "Line %d: Bogus attr name char: %c", lp->ln,c);
+ return (-1);
+ }
+ break;
+
+ case LOOK4ATTRV: /* looking for attr value */
+ if (c == '\'' || c == '"') {
+ lp->delim = c;
+ growString (&lp->ce->at[lp->ce->nat-1]->valu, '\0');
+ lp->cs = INATTRV;
+ } else if (!(isspace(c) || c == '=')) {
+ snprintf (errmsg, ERRMSG_SIZE, "Line %d: No value for attribute %.100s", lp->ln,
+ lp->ce->at[lp->ce->nat-1]->name);
+ return (-1);
+ }
+ break;
+
+ case INATTRV: /* in attr value */
+ if (c == lp->delim)
+ lp->cs = LOOK4ATTRN;
+ else if (!iscntrl(c))
+ growString (&lp->ce->at[lp->ce->nat-1]->valu, c);
+ break;
+
+ case LOOK4CON: /* skipping leading content whitespace*/
+ if (c == '<')
+ lp->cs = LTINCON;
+ else if (!isspace(c)) {
+ growPCData (lp->ce, c);
+ lp->cs = INCON;
+ }
+ break;
+
+ case INCON: /* reading content */
+ if (c == '<') {
+ /* if text contains a nl trim trailing blanks.
+ * chomp trailing nl if only one.
+ */
+ char *nl = strpbrk (lp->ce->pcdata, "\n\r");
+ if (nl)
+ while (lp->ce->pcdatal > 0 &&
+ lp->ce->pcdata[lp->ce->pcdatal-1] == ' ')
+ lp->ce->pcdata[--lp->ce->pcdatal] = '\0';
+ if (nl == &lp->ce->pcdata[lp->ce->pcdatal-1])
+ lp->ce->pcdata[--lp->ce->pcdatal] = '\0'; /* safe! */
+ lp->cs = LTINCON;
+ } else
+ growPCData (lp->ce, c);
+ break;
+
+ case LTINCON: /* saw < in content */
+ if (c == '/') {
+ resetEndTag(lp);
+ lp->cs = LOOK4CLOSETAG;
+ } else {
+ pushXMLEle(lp);
+ if (isTokenChar(1,c)) {
+ growString (&lp->ce->tag, c);
+ lp->cs = INTAG;
+ } else
+ lp->cs = LOOK4TAG;
+ }
+ break;
+
+ case LOOK4CLOSETAG: /* looking for closing tag after < */
+ if (isTokenChar (1, c)) {
+ growString (&lp->endtag, c);
+ lp->cs = INCLOSETAG;
+ } else if (!isspace(c)) {
+ snprintf (errmsg, ERRMSG_SIZE, "Line %d: Bogus preend tag char %c", lp->ln,c);
+ return (-1);
+ }
+ break;
+
+ case INCLOSETAG: /* reading closing tag */
+ if (isTokenChar(0, c))
+ growString (&lp->endtag, c);
+ else if (c == '>') {
+ if (strcmp (lp->ce->tag, lp->endtag)) {
+ snprintf (errmsg, ERRMSG_SIZE, "Line %d: closing tag %.64s does not match %.64s",
+ lp->ln, lp->endtag, lp->ce->tag);
+ return (-1);
+ } else if (lp->ce->pe) {
+ popXMLEle(lp);
+ lp->cs = LOOK4CON; /* back to content after nested elem */
+ } else
+ return (1); /* yes! */
+ } else if (!isspace(c)) {
+ snprintf (errmsg, ERRMSG_SIZE, "Line %d: Bogus end tag char %c", lp->ln, c);
+ return (-1);
+ }
+ break;
+ }
+
+ return (0);
+}
+
+/* set up for a fresh start */
+static void
+initParser(LilXML *lp)
+{
+ memset (lp, 0, sizeof(*lp));
+ lp->cs = LOOK4START;
+ lp->ln = 1;
+ delXMLEle (lp->ce);
+ lp->ce = NULL;
+ resetEndTag(lp);
+ lp->lastc = 0;
+ lp->skipping = 0;
+}
+
+/* start a new XMLEle.
+ * if ce already set up, add to its list of child elements.
+ * point ce to a new XMLEle.
+ * endtag no longer valid.
+ */
+static void
+pushXMLEle(LilXML *lp)
+{
+ XMLEle *newe = (XMLEle *) moremem (NULL, sizeof(XMLEle));
+ XMLEle *ce = lp->ce;
+
+ memset (newe, 0, sizeof(*newe));
+ newe->tag = newString();
+ newe->pcdata = newString();
+ newe->pe = ce;
+
+ if (ce) {
+ ce->el = (XMLEle **) moremem (ce->el, (ce->nel+1)*sizeof(XMLEle*));
+ ce->el[ce->nel++] = newe;
+ }
+ lp->ce = newe;
+ resetEndTag(lp);
+}
+
+/* point ce to parent of current ce.
+ * endtag no longer valid.
+ */
+static void
+popXMLEle(LilXML *lp)
+{
+ lp->ce = lp->ce->pe;
+ resetEndTag(lp);
+}
+
+/* add one new XMLAtt to the current element */
+static void
+addAttr(LilXML *lp)
+{
+ XMLAtt *newa = (XMLAtt *) moremem (NULL, sizeof(XMLAtt));
+ XMLEle *ce = lp->ce;
+
+ memset (newa, 0, sizeof(*newa));
+ newa->name = newString();
+ newa->valu = newString();
+ newa->ce = ce;
+
+ ce->at = (XMLAtt **) moremem (ce->at, (ce->nat+1)*sizeof(XMLAtt *));
+ ce->at[ce->nat++] = newa;
+}
+
+/* delete a and all it holds */
+static void
+delAttr (XMLAtt *a)
+{
+ if (!a)
+ return;
+ if (a->name)
+ freemem (a->name);
+ if (a->valu)
+ freemem (a->valu);
+ freemem(a);
+}
+
+/* delete endtag if appropriate */
+static void
+resetEndTag(LilXML *lp)
+{
+ if (lp->endtag) {
+ freemem (lp->endtag);
+ lp->endtag = 0;
+ }
+}
+
+/* 1 if c is a valid token character, else 0.
+ * it can be alpha or '_' or numeric unless start.
+ */
+static int
+isTokenChar (int start, int c)
+{
+ return (isalpha(c) || c == '_' || (!start && isdigit(c)));
+}
+
+/* grow the malloced string at *sp to append c */
+static void
+growString (char **sp, int c)
+{
+ int l = *sp ? strlen(*sp) : 0;
+ *sp = (char *) moremem (*sp, l+2); /* c + '\0' */
+ (*sp)[l++] = (char)c;
+ (*sp)[l] = '\0';
+}
+
+/* special fast version of growString just for ep->pcdata that avoids all the
+ * strlens and tiny increments in allocated mem
+ */
+static void
+growPCData (XMLEle *ep, int c)
+{
+ int l = ep->pcdatal++;
+ if ((l%32) == 0) {
+ int nm = 32*(l/32+1) + 2; /* c + '\0' */
+ ep->pcdata = (char *) moremem (ep->pcdata, nm);
+ }
+ ep->pcdata[l++] = (char)c;
+ ep->pcdata[l] = '\0';
+}
+
+/* return a malloced string of one '\0' */
+static char *
+newString()
+{
+ char *str;
+
+ *(str = (char *)moremem(NULL, 16)) = '\0'; /* expect more */
+ return (str);
+}
+
+static void *
+moremem (void *old, int n)
+{
+ return (old ? realloc (old, n) : malloc (n));
+}
+
+static void
+freemem (void *m)
+{
+ free (m);
+}
+
+#if defined(MAIN_TST)
+int
+main (int ac, char *av[])
+{
+ LilXML *lp = newLilXML();
+ char errmsg[ERRMSG_SIZE];
+ XMLEle *root;
+
+ root = readXMLFile (stdin, lp, errmsg);
+ if (root) {
+ fprintf (stderr, "::::::::::::: %s\n", tagXMLEle(root));
+ prXMLEle (stdout, root, 0);
+ delXMLEle (root);
+ } else if (errmsg[0]) {
+ fprintf (stderr, "Error: %s\n", errmsg);
+ }
+
+ delLilXML (lp);
+
+ return (0);
+}
+#endif
+
diff --git a/kstars/kstars/indi/lilxml.h b/kstars/kstars/indi/lilxml.h
new file mode 100644
index 00000000..98bfdd2b
--- /dev/null
+++ b/kstars/kstars/indi/lilxml.h
@@ -0,0 +1,252 @@
+#if 0
+ liblilxml
+ Copyright (C) 2003 Elwood C. Downey
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+/** \file lilxml.h
+ \brief A little DOM-style library to handle parsing and processing an XML file.
+
+ It only handles elements, attributes and pcdata content. <! ... > and <? ... > are silently ignored. pcdata is collected into one string, sans leading whitespace first line. \n
+
+ The following is an example of a cannonical usage for the lilxml library. Initialize a lil xml context and read an XML file in a root element.
+
+ \code
+
+ #include <lilxml.h>
+
+ LilXML *lp = newLilXML();
+ char errmsg[1024];
+ XMLEle *root, *ep;
+ int c;
+
+ while ((c = fgetc(stdin)) != EOF) {
+ root = readXMLEle (lp, c, errmsg);
+ if (root)
+ break;
+ if (errmsg[0])
+ error ("Error: %s\n", errmsg);
+ }
+
+ // print the tag and pcdata content of each child element within the root
+
+ for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0))
+ printf ("%s: %s\n", tagXMLEle(ep), pcdataXMLEle(ep));
+
+
+ // finished with root element and with lil xml context
+
+ delXMLEle (root);
+ delLilXML (lp);
+
+ \endcode
+
+ */
+
+#ifndef LILXML_H
+#define LILXML_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* opaque handle types */
+typedef struct _xml_att XMLAtt;
+typedef struct _xml_ele XMLEle;
+typedef struct _LilXML LilXML;
+
+/**
+ * \defgroup lilxmlFunctions Functions to parse, process, and search XML.
+ */
+/*@{*/
+
+/* creation and destruction functions */
+
+/** \brief Create a new lilxml parser.
+ \return a pointer to the lilxml parser on sucess. NULL on failure.
+*/
+extern LilXML *newLilXML(void);
+
+/** \brief Delete a lilxml parser.
+ \param lp a pointer to a lilxml parser to be deleted.
+*/
+extern void delLilXML (LilXML *lp);
+
+/** \brief Delete an XML element.
+ \return a pointer to the XML Element to be deleted.
+*/
+extern void delXMLEle (XMLEle *e);
+
+/** \brief Process an XML one char at a time.
+ \param lp a pointer to a lilxml parser.
+ \param c one character to process.
+ \param errmsg a buffer to store error messages if an error in parsing is encounterd.
+ \return When the function parses a complete valid XML element, it will return a pointer to the XML element. A NULL is returned when parsing the element is still in progress, or if a parsing error occurs. Check errmsg for errors if NULL is returned.
+ */
+extern XMLEle *readXMLEle (LilXML *lp, int c, char errmsg[]);
+
+/* search functions */
+/** \brief Find an XML attribute within an XML element.
+ \param e a pointer to the XML element to search.
+ \param name the attribute name to search for.
+ \return A pointer to the XML attribute if found or NULL on failure.
+*/
+extern XMLAtt *findXMLAtt (XMLEle *e, const char *name);
+
+/** \brief Find an XML element within an XML element.
+ \param e a pointer to the XML element to search.
+ \param tag the element tag to search for.
+ \return A pointer to the XML element if found or NULL on failure.
+*/
+extern XMLEle *findXMLEle (XMLEle *e, const char *tag);
+
+/* iteration functions */
+/** \brief Iterate an XML element for a list of nesetd XML elements.
+ \param ep a pointer to the XML element to iterate.
+ \param first the index of the starting XML element. Pass 1 to start iteration from the beginning of the XML element. Pass 0 to get the next element thereater.
+ \return On success, a pointer to the next XML element is returned. NULL when there are no more elements.
+*/
+extern XMLEle *nextXMLEle (XMLEle *ep, int first);
+
+/** \brief Iterate an XML element for a list of XML attributes.
+ \param ep a pointer to the XML element to iterate.
+ \param first the index of the starting XML attribute. Pass 1 to start iteration from the beginning of the XML element. Pass 0 to get the next attribute thereater.
+ \return On success, a pointer to the next XML attribute is returned. NULL when there are no more attributes.
+*/
+extern XMLAtt *nextXMLAtt (XMLEle *ep, int first);
+
+/* tree functions */
+/** \brief Return the parent of an XML element.
+ \return a pointer to the XML element parent.
+*/
+extern XMLEle *parentXMLEle (XMLEle *ep);
+
+/** \brief Return the parent of an XML attribute.
+ \return a pointer to the XML element parent.
+*/
+extern XMLEle *parentXMLAtt (XMLAtt *ap);
+
+/* access functions */
+/** \brief Return the tag of an XML element.
+ \param ep a pointer to an XML element.
+ \return the tag string.
+*/
+extern char *tagXMLEle (XMLEle *ep);
+
+/** \brief Return the pcdata of an XML element.
+ \param ep a pointer to an XML element.
+ \return the pcdata string on success.
+*/
+extern char *pcdataXMLEle (XMLEle *ep);
+
+/** \brief Return the name of an XML attribute.
+ \param ap a pointer to an XML attribute.
+ \return the name string of the attribute.
+*/
+extern char *nameXMLAtt (XMLAtt *ap);
+
+/** \brief Return the value of an XML attribute.
+ \param ap a pointer to an XML attribute.
+ \return the value string of the attribute.
+*/
+extern char *valuXMLAtt (XMLAtt *ap);
+
+/** \brief Return the number of characters in pcdata in an XML element.
+ \param ep a pointer to an XML element.
+ \return the length of the pcdata string.
+*/
+extern int pcdatalenXMLEle (XMLEle *ep);
+
+/** \brief Return the number of nested XML elements in a parent XML element.
+ \param ep a pointer to an XML element.
+ \return the number of nested XML elements.
+*/
+extern int nXMLEle (XMLEle *ep);
+
+/** \brief Return the number of XML attributes in a parent XML element.
+ \param ep a pointer to an XML element.
+ \return the number of XML attributes within the XML element.
+*/
+extern int nXMLAtt (XMLEle *ep);
+
+/* convenience functions */
+/** \brief Find an XML element's attribute value.
+ \param ep a pointer to an XML element.
+ \param name the name of the XML attribute to retrieve its value.
+ \return the value string of an XML element on success. NULL on failure.
+*/
+extern const char *findXMLAttValu (XMLEle *ep, char *name);
+
+/** \brief Handy wrapper to read one xml file.
+ \param fp pointer to FILE to read.
+ \param lp pointer to lilxml parser.
+ \param errmsg a buffer to store error messages on failure.
+ \return root element else NULL with report in errmsg[].
+*/
+extern XMLEle *readXMLFile (FILE *fp, LilXML *lp, char errmsg[]);
+
+/** \brief Print an XML element.
+ \param fp a pointer to FILE where the print output is directed.
+ \param e the XML element to print.
+ \param level the printing level, set to 0 to print the whole element.
+*/
+extern void prXMLEle (FILE *fp, XMLEle *e, int level);
+
+/* install alternatives to malloc/realloc/free */
+extern void indi_xmlMalloc (void *(*newmalloc)(size_t size),
+ void *(*newrealloc)(void *ptr, size_t size), void (*newfree)(void *ptr));
+
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+/* examples.
+
+ initialize a lil xml context and read an XML file in a root element
+
+ LilXML *lp = newLilXML();
+ char errmsg[1024];
+ XMLEle *root, *ep;
+ int c;
+
+ while ((c = fgetc(stdin)) != EOF) {
+ root = readXMLEle (lp, c, errmsg);
+ if (root)
+ break;
+ if (errmsg[0])
+ error ("Error: %s\n", errmsg);
+ }
+
+ print the tag and pcdata content of each child element within the root
+
+ for (ep = nextXMLEle (root, 1); ep != NULL; ep = nextXMLEle (root, 0))
+ printf ("%s: %s\n", tagXMLEle(ep), pcdataXMLEle(ep));
+
+
+ finished with root element and with lil xml context
+
+ delXMLEle (root);
+ delLilXML (lp);
+ */
+
+/* For RCS Only -- Do Not Edit
+ * @(#) $RCSfile$ $Date$ $Revision$ $Name: $
+ */
+
+#endif /* LILXML_H */
diff --git a/kstars/kstars/indi/lx200_16.cpp b/kstars/kstars/indi/lx200_16.cpp
new file mode 100644
index 00000000..fe37df18
--- /dev/null
+++ b/kstars/kstars/indi/lx200_16.cpp
@@ -0,0 +1,396 @@
+/*
+ LX200 16"
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "lx200_16.h"
+#include "lx200driver.h"
+
+#define LX16GROUP "GPS/16 inch Features"
+
+extern LX200Generic *telescope;
+extern ITextVectorProperty Time;
+extern int MaxReticleFlashRate;
+
+
+//void turnFanOn();
+ //void turnFanOff();
+
+ //void seekHomeAndSave();
+ // void seekHomeAndSet();
+
+ /** Turns the field derotator On or Off. This command applies <b>only</b> to 16" LX200.
+ @param turnOn if turnOn is true, the derotator is turned on, otherwise, it is turned off. */
+ // void fieldDeRotator(bool turnOn);
+
+
+ /** Sets object Altitude. \n
+ @returns true if object's altitude is successfully set. */
+ //bool setObjAlt(int degrees, int minutes);
+
+ /** Sets object Azimuth. \n
+ @returns true if object's azimuth is successfully set. */
+// bool setObjAz(int degrees, int minutes);
+
+
+static ISwitch FanStatusS[] = { {"On", "", ISS_OFF, 0, 0}, {"Off", "", ISS_OFF, 0, 0}};
+static ISwitch HomeSearchS[] = { {"Save home", "", ISS_OFF, 0, 0} , {"Set home", "", ISS_OFF, 0, 0}};
+static ISwitch FieldDeRotatorS[] = { {"On", "", ISS_OFF, 0, 0}, {"Off", "", ISS_OFF,0 ,0}};
+//static ISwitch SlewAltAzS[] = { {"Slew To Alt/Az", ISS_ON}};
+
+#define MAXINDINAME 32
+#define MAXINDILABEL 32
+#define MAXINDIDEVICE 32
+#define MAXINDIGROUP 32
+#define MAXINDIFORMAT 32
+
+static ISwitchVectorProperty FanStatusSw = { mydev, "Fan", "", LX16GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, FanStatusS, NARRAY(FanStatusS), "", 0};
+
+static ISwitchVectorProperty HomeSearchSw = { mydev, "Park", "", LX16GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, HomeSearchS, NARRAY(HomeSearchS), "", 0};
+
+static ISwitchVectorProperty FieldDeRotatorSw = { mydev, "Field De-rotator", "", LX16GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, FieldDeRotatorS, NARRAY(FieldDeRotatorS), "", 0};
+
+//static ISwitches SlewAltAzSw = { mydev, "AltAzSet", "On Alt/Az Set", SlewAltAzS, NARRAY(SlewAltAzS), ILS_IDLE, 0, LX16Group};
+
+/* horizontal position */
+static INumber hor[] = {
+ {"ALT", "Alt D:M:S", "%10.6m", -90., 90., 0., 0., 0, 0, 0},
+ {"AZ", "Az D:M:S", "%10.6m", 0., 360., 0., 0., 0, 0, 0}};
+
+static INumberVectorProperty horNum = {
+ mydev, "HORIZONTAL_COORD", "Horizontal Coords", LX16GROUP, IP_RW, 0, IPS_IDLE,
+ hor, NARRAY(hor), "", 0};
+
+void changeLX200_16DeviceName(const char * newName)
+{
+ strcpy(horNum.device, newName);
+ strcpy(FanStatusSw.device, newName);
+ strcpy(HomeSearchSw.device, newName);
+ strcpy(FieldDeRotatorSw.device,newName);
+}
+
+LX200_16::LX200_16() : LX200Autostar()
+{
+
+}
+
+void LX200_16::ISGetProperties (const char *dev)
+{
+
+if (dev && strcmp (thisDevice, dev))
+ return;
+
+ // process parent first
+ LX200Autostar::ISGetProperties(dev);
+
+ IDDefNumber (&horNum, NULL);
+
+ IDDefSwitch (&FanStatusSw, NULL);
+ IDDefSwitch (&HomeSearchSw, NULL);
+ IDDefSwitch (&FieldDeRotatorSw, NULL);
+
+}
+
+void LX200_16::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+
+ // ignore if not ours //
+ if (strcmp (dev, thisDevice))
+ return;
+
+ LX200Autostar::ISNewText (dev, name, texts, names, n);
+
+}
+
+void LX200_16::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ double newAlt=0, newAz=0;
+ char altStr[64], azStr[64];
+ int err;
+
+ // ignore if not ours //
+ if (strcmp (dev, thisDevice))
+ return;
+
+ if ( !strcmp (name, horNum.name) )
+ {
+ int i=0, nset=0;
+
+ if (checkPower(&horNum))
+ return;
+
+ for (nset = i = 0; i < n; i++)
+ {
+ INumber *horp = IUFindNumber (&horNum, names[i]);
+ if (horp == &hor[0])
+ {
+ newAlt = values[i];
+ nset += newAlt >= -90. && newAlt <= 90.0;
+ } else if (horp == &hor[1])
+ {
+ newAz = values[i];
+ nset += newAz >= 0. && newAz <= 360.0;
+ }
+ }
+
+ if (nset == 2)
+ {
+ if ( (err = setObjAz(newAz)) < 0 || (err = setObjAlt(newAlt)) < 0)
+ {
+ handleError(&horNum, err, "Setting Alt/Az");
+ return;
+ }
+ horNum.s = IPS_OK;
+ //horNum.n[0].value = values[0];
+ //horNum.n[1].value = values[1];
+ targetAz = newAz;
+ targetAlt = newAlt;
+
+ fs_sexa(azStr, targetAz, 2, 3600);
+ fs_sexa(altStr, targetAlt, 2, 3600);
+
+ IDSetNumber (&horNum, "Attempting to slew to Alt %s - Az %s", altStr, azStr);
+ handleAltAzSlew();
+ }
+ else
+ {
+ horNum.s = IPS_IDLE;
+ IDSetNumber(&horNum, "Altitude or Azimuth missing or invalid");
+ }
+
+ return;
+ }
+
+ LX200Autostar::ISNewNumber (dev, name, values, names, n);
+}
+
+
+
+
+void LX200_16::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ int index;
+ int err;
+
+ if (strcmp (dev, thisDevice))
+ return;
+
+ if (!strcmp(name, FanStatusSw.name))
+ {
+ if (checkPower(&FanStatusSw))
+ return;
+
+ IUResetSwitches(&FanStatusSw);
+ IUUpdateSwitches(&FanStatusSw, states, names, n);
+ index = getOnSwitch(&FanStatusSw);
+
+ if (index == 0)
+ {
+ if ( (err = turnFanOn()) < 0)
+ {
+ handleError(&FanStatusSw, err, "Changing fan status");
+ return;
+ }
+ }
+ else
+ {
+ if ( (err = turnFanOff()) < 0)
+ {
+ handleError(&FanStatusSw, err, "Changing fan status");
+ return;
+ }
+ }
+
+ FanStatusSw.s = IPS_OK;
+ IDSetSwitch (&FanStatusSw, index == 0 ? "Fan is ON" : "Fan is OFF");
+ return;
+ }
+
+ if (!strcmp(name, HomeSearchSw.name))
+ {
+ if (checkPower(&HomeSearchSw))
+ return;
+
+ IUResetSwitches(&HomeSearchSw);
+ IUUpdateSwitches(&HomeSearchSw, states, names, n);
+ index = getOnSwitch(&HomeSearchSw);
+
+ index == 0 ? seekHomeAndSave() : seekHomeAndSet();
+ HomeSearchSw.s = IPS_BUSY;
+ IDSetSwitch (&HomeSearchSw, index == 0 ? "Seek Home and Save" : "Seek Home and Set");
+ return;
+ }
+
+ if (!strcmp(name, FieldDeRotatorSw.name))
+ {
+ if (checkPower(&FieldDeRotatorSw))
+ return;
+
+ IUResetSwitches(&FieldDeRotatorSw);
+ IUUpdateSwitches(&FieldDeRotatorSw, states, names, n);
+ index = getOnSwitch(&FieldDeRotatorSw);
+
+ index == 0 ? seekHomeAndSave() : seekHomeAndSet();
+ FieldDeRotatorSw.s = IPS_OK;
+ IDSetSwitch (&FieldDeRotatorSw, index == 0 ? "Field deRotator is ON" : "Field deRotator is OFF");
+ return;
+ }
+
+ LX200Autostar::ISNewSwitch (dev, name, states, names, n);
+
+}
+
+void LX200_16::handleAltAzSlew()
+{
+ int i=0;
+ char altStr[64], azStr[64];
+
+ if (horNum.s == IPS_BUSY)
+ {
+ abortSlew();
+
+ // sleep for 100 mseconds
+ usleep(100000);
+ }
+
+ if ((i = slewToAltAz()))
+ {
+ horNum.s = IPS_IDLE;
+ IDSetNumber(&horNum, "Slew not possible");
+ return;
+ }
+
+ horNum.s = IPS_BUSY;
+ fs_sexa(azStr, targetAz, 2, 3600);
+ fs_sexa(altStr, targetAlt, 2, 3600);
+
+ IDSetNumber(&horNum, "Slewing to Alt %s - Az %s", altStr, azStr);
+ return;
+}
+
+ void LX200_16::ISPoll ()
+ {
+ int searchResult=0;
+ double dx, dy;
+ int err;
+
+ LX200Autostar::ISPoll();
+
+ switch (HomeSearchSw.s)
+ {
+ case IPS_IDLE:
+ break;
+
+ case IPS_BUSY:
+
+ if ( (err = getHomeSearchStatus(&searchResult)) < 0)
+ {
+ handleError(&HomeSearchSw, err, "Home search");
+ return;
+ }
+
+ if (searchResult == 0)
+ {
+ HomeSearchSw.s = IPS_IDLE;
+ IDSetSwitch(&HomeSearchSw, "Home search failed.");
+ }
+ else if (searchResult == 1)
+ {
+ HomeSearchSw.s = IPS_OK;
+ IDSetSwitch(&HomeSearchSw, "Home search successful.");
+ }
+ else if (searchResult == 2)
+ IDSetSwitch(&HomeSearchSw, "Home search in progress...");
+ else
+ {
+ HomeSearchSw.s = IPS_IDLE;
+ IDSetSwitch(&HomeSearchSw, "Home search error.");
+ }
+ break;
+
+ case IPS_OK:
+ break;
+ case IPS_ALERT:
+ break;
+ }
+
+ switch (horNum.s)
+ {
+ case IPS_IDLE:
+ break;
+
+ case IPS_BUSY:
+
+ if ( (err = getLX200Az(&currentAz)) < 0 || (err = getLX200Alt(&currentAlt)) < 0)
+ {
+ IDSetNumber(&horNum, NULL);
+ handleError(&horNum, err, "Get Alt/Az");
+ return;
+ }
+
+ dx = targetAz - currentAz;
+ dy = targetAlt - currentAlt;
+
+ horNum.np[0].value = currentAlt;
+ horNum.np[1].value = currentAz;
+
+ IDLog("targetAz is %g, currentAz is %g\n", targetAz, currentAz);
+ IDLog("targetAlt is %g, currentAlt is %g\n**********************\n", targetAlt, currentAlt);
+
+
+ // accuracy threshhold (3'), can be changed as desired.
+ if ( fabs(dx) <= 0.05 && fabs(dy) <= 0.05)
+ {
+
+ horNum.s = IPS_OK;
+ currentAz = targetAz;
+ currentAlt = targetAlt;
+ IDSetNumber (&horNum, "Slew is complete");
+ } else
+ IDSetNumber (&horNum, NULL);
+ break;
+
+ case IPS_OK:
+ break;
+
+ case IPS_ALERT:
+ break;
+ }
+
+ }
+
+ void LX200_16::getBasicData()
+ {
+
+ getLX200Az(&targetAz);
+ getLX200Alt(&targetAlt);
+
+ horNum.np[0].value = targetAlt;
+ horNum.np[1].value = targetAz;
+
+ IDSetNumber (&horNum, NULL);
+
+ LX200Autostar::getBasicData();
+
+ }
diff --git a/kstars/kstars/indi/lx200_16.h b/kstars/kstars/indi/lx200_16.h
new file mode 100644
index 00000000..0d353cc2
--- /dev/null
+++ b/kstars/kstars/indi/lx200_16.h
@@ -0,0 +1,53 @@
+#ifndef LX200_16_H
+#define LX200_16_H
+
+/*
+ LX200 16"
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include "lx200autostar.h"
+
+class LX200_16 : public LX200Autostar
+{
+ public:
+ LX200_16();
+ ~LX200_16() {}
+
+ void ISGetProperties (const char *dev);
+ void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+ void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+ void ISPoll ();
+ void getBasicData();
+ void handleAltAzSlew();
+
+ private:
+
+ double currentAlt;
+ double currentAz;
+ double targetAlt;
+ double targetAz;
+
+};
+
+void changeLX200_16DeviceName(const char * newName);
+
+#endif
+
+
diff --git a/kstars/kstars/indi/lx200autostar.cpp b/kstars/kstars/indi/lx200autostar.cpp
new file mode 100644
index 00000000..79c3d575
--- /dev/null
+++ b/kstars/kstars/indi/lx200autostar.cpp
@@ -0,0 +1,154 @@
+/*
+ LX200 Autostar
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "lx200autostar.h"
+#include "lx200driver.h"
+
+#define FirmwareGroup "Firmware data"
+
+
+extern LX200Generic *telescope;
+extern int MaxReticleFlashRate;
+extern ITextVectorProperty Time;
+extern INumberVectorProperty SDTime;
+extern INumberVectorProperty eqNum;
+extern ISwitchVectorProperty ParkSP;
+extern ISwitchVectorProperty PowerSP;
+
+static IText VersionT[] ={{ "Date", "", 0, 0, 0, 0} ,
+ { "Time", "", 0, 0, 0, 0} ,
+ { "Number", "", 0, 0, 0 ,0} ,
+ { "Full", "", 0, 0, 0, 0} ,
+ { "Name", "" ,0 ,0 ,0 ,0}};
+
+static ITextVectorProperty VersionInfo = {mydev, "Firmware Info", "", FirmwareGroup, IP_RO, 0, IPS_IDLE, VersionT, NARRAY(VersionT), "" ,0};
+
+void changeLX200AutostarDeviceName(const char *newName)
+{
+ strcpy(VersionInfo.device, newName);
+}
+
+LX200Autostar::LX200Autostar() : LX200Generic()
+{
+
+ //for (int i=0; i < 5; i++)
+ //strcpy(VersionInfo.t[i].text, "");
+
+}
+
+
+void LX200Autostar::ISGetProperties (const char *dev)
+{
+
+if (dev && strcmp (thisDevice, dev))
+ return;
+
+ LX200Generic::ISGetProperties(dev);
+
+ IDDefText (&VersionInfo, NULL);
+
+}
+
+void LX200Autostar::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+ // ignore if not ours //
+ if (strcmp (dev, thisDevice))
+ return;
+
+ // suppress warning
+ n=n;
+
+ LX200Generic::ISNewText (dev, name, texts, names, n);
+
+}
+
+
+void LX200Autostar::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ LX200Generic::ISNewNumber (dev, name, values, names, n);
+}
+
+ void LX200Autostar::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+ {
+
+ if (!strcmp(name, ParkSP.name))
+ {
+ if (checkPower(&ParkSP))
+ return;
+
+ ParkSP.s = IPS_IDLE;
+
+ if (eqNum.s == IPS_BUSY)
+ {
+ abortSlew();
+
+ // sleep for 200 mseconds
+ usleep(200000);
+ }
+
+ slewToPark();
+
+ ParkSP.s = IPS_OK;
+ eqNum.s = IPS_IDLE;
+ PowerSP.s = IPS_IDLE;
+ PowerSP.sp[0].s = ISS_OFF;
+ PowerSP.sp[1].s = ISS_ON;
+ IDSetNumber(&eqNum, NULL);
+ IDSetSwitch(&ParkSP, "The telescope is slewing to park position. Turn off the telescope after park is complete. Disconnecting...");
+ IDSetSwitch(&PowerSP, NULL);
+ return;
+ }
+
+ LX200Generic::ISNewSwitch (dev, name, states, names, n);
+
+ }
+
+ void LX200Autostar::ISPoll ()
+ {
+
+ LX200Generic::ISPoll();
+
+ }
+
+ void LX200Autostar::getBasicData()
+ {
+
+ VersionInfo.tp[0].text = new char[64];
+ getVersionDate(VersionInfo.tp[0].text);
+ VersionInfo.tp[1].text = new char[64];
+ getVersionTime(VersionInfo.tp[1].text);
+ VersionInfo.tp[2].text = new char[64];
+ getVersionNumber(VersionInfo.tp[2].text);
+ VersionInfo.tp[3].text = new char[128];
+ getFullVersion(VersionInfo.tp[3].text);
+ VersionInfo.tp[4].text = new char[128];
+ getProductName(VersionInfo.tp[4].text);
+
+ IDSetText(&VersionInfo, NULL);
+
+ // process parent
+ LX200Generic::getBasicData();
+
+ }
diff --git a/kstars/kstars/indi/lx200autostar.h b/kstars/kstars/indi/lx200autostar.h
new file mode 100644
index 00000000..665939a8
--- /dev/null
+++ b/kstars/kstars/indi/lx200autostar.h
@@ -0,0 +1,45 @@
+/*
+ LX200 Autostar
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef LX200AUTOSTAR_H
+#define LX200AUTOSTAR_H
+
+#include "lx200generic.h"
+
+class LX200Autostar : public LX200Generic
+{
+ public:
+ LX200Autostar();
+ ~LX200Autostar() {}
+
+ void ISGetProperties (const char *dev);
+ void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+ void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+ void ISPoll ();
+ void getBasicData();
+
+
+};
+
+void changeLX200AutostarDeviceName(const char *newName);
+
+#endif
+
diff --git a/kstars/kstars/indi/lx200basic.cpp b/kstars/kstars/indi/lx200basic.cpp
new file mode 100644
index 00000000..a812caa6
--- /dev/null
+++ b/kstars/kstars/indi/lx200basic.cpp
@@ -0,0 +1,839 @@
+#if 0
+ LX200 Basic Driver
+ Copyright (C) 2005 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "indicom.h"
+#include "lx200driver.h"
+#include "lx200basic.h"
+
+/*
+** Return the timezone offset in hours (as a double, so fractional
+** hours are possible, for instance in Newfoundland). Also sets
+** daylight on non-Linux systems to record whether DST is in effect.
+*/
+
+
+LX200Basic *telescope = NULL;
+extern char* me;
+
+#define BASIC_GROUP "Main Control"
+
+#define currentRA EqN[0].value
+#define currentDEC EqN[1].value
+
+#define RA_THRESHOLD 0.01
+#define DEC_THRESHOLD 0.05
+#define LX200_SLEW 0
+#define LX200_TRACK 1
+#define LX200_SYNC 2
+#define LX200_PARK 3
+
+static void ISPoll(void *);
+static void retryConnection(void *);
+
+/*INDI controls */
+
+
+/* send client definitions of all properties */
+void ISInit()
+{
+ static int isInit=0;
+
+ if (isInit)
+ return;
+
+ isInit = 1;
+
+ telescope = new LX200Basic();
+ IEAddTimer (POLLMS, ISPoll, NULL);
+}
+
+void ISGetProperties (const char *dev)
+{
+ ISInit();
+ telescope->ISGetProperties(dev);
+}
+
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ ISInit();
+ telescope->ISNewSwitch(dev, name, states, names, n);
+}
+
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+ ISInit();
+ telescope->ISNewText(dev, name, texts, names, n);
+}
+
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ ISInit();
+ telescope->ISNewNumber(dev, name, values, names, n);
+}
+
+void ISPoll (void */*p*/)
+{
+ telescope->ISPoll();
+ IEAddTimer (POLLMS, ISPoll, NULL);
+}
+
+void ISNewBLOB (const char */*dev*/, const char */*name*/, int */*sizes[]*/, char **/*blobs[]*/, char **/*formats[]*/, char **/*names[]*/, int /*n*/)
+{}
+
+/**************************************************
+*** AP Mount
+***************************************************/
+
+LX200Basic::LX200Basic()
+{
+ struct tm *utp;
+ time_t t;
+ time (&t);
+ utp = gmtime (&t);
+
+ initProperties();
+
+ lastSet = -1;
+ simulation = false;
+ targetRA = 0;
+ targetDEC = 0;
+ lastRA = 0;
+ lastDEC = 0;
+ currentSet = 0;
+ UTCOffset = 0;
+
+ localTM = new tm;
+
+ utp->tm_mon += 1;
+ utp->tm_year += 1900;
+ JD = UTtoJD(utp);
+
+ IDLog("Julian Day is %g\n", JD);
+ IDLog("Initilizing from LX200 Basic device...\n");
+ IDLog("Driver Version: 2005-07-20\n");
+
+ //enableSimulation(true);
+}
+
+void LX200Basic::initProperties()
+{
+
+ fillSwitch(&PowerS[0], "CONNECT", "Connect", ISS_OFF);
+ fillSwitch(&PowerS[1], "DISCONNECT", "Disconnect", ISS_ON);
+ fillSwitchVector(&PowerSP, PowerS, NARRAY(PowerS), mydev, "CONNECTION", "Connection", BASIC_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
+
+ fillSwitch(&OnCoordSetS[0], "SLEW", "Slew", ISS_ON);
+ fillSwitch(&OnCoordSetS[1], "TRACK", "Track", ISS_OFF);
+ fillSwitch(&OnCoordSetS[2], "SYNC", "Sync", ISS_OFF);
+ fillSwitchVector(&OnCoordSetSP, OnCoordSetS, NARRAY(OnCoordSetS), mydev, "ON_COORD_SET", "On Set", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ fillSwitch(&AbortSlewS[0], "ABORT", "Abort", ISS_OFF);
+ fillSwitchVector(&AbortSlewSP, AbortSlewS, NARRAY(AbortSlewS), mydev, "ABORT_MOTION", "Abort Slew/Track", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ fillText(&PortT[0], "PORT", "Port", "/dev/ttyS0");
+ fillTextVector(&PortTP, PortT, NARRAY(PortT), mydev, "DEVICE_PORT", "Ports", BASIC_GROUP, IP_RW, 0, IPS_IDLE);
+
+ fillText(&ObjectT[0], "OBJECT_NAME", "Name", "--");
+ fillTextVector(&ObjectTP, ObjectT, NARRAY(ObjectT), mydev, "OBJECT_INFO", "Object", BASIC_GROUP, IP_RW, 0, IPS_IDLE);
+
+ fillNumber(&EqN[0], "RA", "RA H:M:S", "%10.6m", 0., 24., 0., 0.);
+ fillNumber(&EqN[1], "DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0.);
+ fillNumberVector(&EqNP, EqN, NARRAY(EqN), mydev, "EQUATORIAL_EOD_COORD" , "Equatorial JNow", BASIC_GROUP, IP_RW, 0, IPS_IDLE);
+
+
+}
+
+void LX200Basic::ISGetProperties(const char *dev)
+{
+
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ // Main Control
+ IDDefSwitch(&PowerSP, NULL);
+ IDDefText(&PortTP, NULL);
+ IDDefText(&ObjectTP, NULL);
+ IDDefNumber(&EqNP, NULL);
+ IDDefSwitch(&OnCoordSetSP, NULL);
+ IDDefSwitch(&AbortSlewSP, NULL);
+
+}
+
+void LX200Basic::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int /*n*/)
+{
+ IText *tp;
+
+ // ignore if not ours
+ if (strcmp (dev, mydev))
+ return;
+
+ // Port name
+ if (!strcmp(name, PortTP.name) )
+ {
+ PortTP.s = IPS_OK;
+ tp = IUFindText( &PortTP, names[0] );
+ if (!tp)
+ return;
+
+ IUSaveText(tp, texts[0]);
+ IDSetText (&PortTP, NULL);
+ return;
+ }
+
+ if (!strcmp (name, ObjectTP.name))
+ {
+ if (checkPower(&ObjectTP))
+ return;
+
+ IUSaveText(&ObjectT[0], texts[0]);
+ ObjectTP.s = IPS_OK;
+ IDSetText(&ObjectTP, NULL);
+ return;
+ }
+
+}
+
+
+void LX200Basic::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ int err;
+ double newRA =0, newDEC =0;
+
+ // ignore if not ours //
+ if (strcmp (dev, mydev))
+ return;
+
+ if (!strcmp (name, EqNP.name))
+ {
+ int i=0, nset=0;
+
+ if (checkPower(&EqNP))
+ return;
+
+ for (nset = i = 0; i < n; i++)
+ {
+ INumber *eqp = IUFindNumber (&EqNP, names[i]);
+ if (eqp == &EqN[0])
+ {
+ newRA = values[i];
+ nset += newRA >= 0 && newRA <= 24.0;
+ } else if (eqp == &EqN[1])
+ {
+ newDEC = values[i];
+ nset += newDEC >= -90.0 && newDEC <= 90.0;
+ }
+ }
+
+ if (nset == 2)
+ {
+ char RAStr[32], DecStr[32];
+
+ fs_sexa(RAStr, newRA, 2, 3600);
+ fs_sexa(DecStr, newDEC, 2, 3600);
+
+ IDLog("We received JNow RA %g - DEC %g\n", newRA, newDEC);
+ IDLog("We received JNow RA %s - DEC %s\n", RAStr, DecStr);
+
+ if ( (err = setObjectRA(newRA)) < 0 || ( err = setObjectDEC(newDEC)) < 0)
+ {
+ handleError(&EqNP, err, "Setting RA/DEC");
+ return;
+ }
+
+ targetRA = newRA;
+ targetDEC = newDEC;
+
+ if (handleCoordSet())
+ {
+ EqNP.s = IPS_IDLE;
+ IDSetNumber(&EqNP, NULL);
+
+ }
+ } // end nset
+ else
+ {
+ EqNP.s = IPS_IDLE;
+ IDSetNumber(&EqNP, "RA or Dec missing or invalid");
+ }
+
+ return;
+ } /* end EqNP */
+
+
+}
+
+void LX200Basic::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ // ignore if not ours //
+ if (strcmp (mydev, dev))
+ return;
+
+ // Connection
+ if (!strcmp (name, PowerSP.name))
+ {
+ IUResetSwitches(&PowerSP);
+ IUUpdateSwitches(&PowerSP, states, names, n);
+ powerTelescope();
+ return;
+ }
+
+ // Coord set
+ if (!strcmp(name, OnCoordSetSP.name))
+ {
+ if (checkPower(&OnCoordSetSP))
+ return;
+
+ IUResetSwitches(&OnCoordSetSP);
+ IUUpdateSwitches(&OnCoordSetSP, states, names, n);
+ currentSet = getOnSwitch(&OnCoordSetSP);
+ OnCoordSetSP.s = IPS_OK;
+ IDSetSwitch(&OnCoordSetSP, NULL);
+ }
+
+ // Abort Slew
+ if (!strcmp (name, AbortSlewSP.name))
+ {
+ if (checkPower(&AbortSlewSP))
+ {
+ AbortSlewSP.s = IPS_IDLE;
+ IDSetSwitch(&AbortSlewSP, NULL);
+ return;
+ }
+
+ IUResetSwitches(&AbortSlewSP);
+ abortSlew();
+
+ if (EqNP.s == IPS_BUSY)
+ {
+ AbortSlewSP.s = IPS_OK;
+ EqNP.s = IPS_IDLE;
+ IDSetSwitch(&AbortSlewSP, "Slew aborted.");
+ IDSetNumber(&EqNP, NULL);
+ }
+
+ return;
+ }
+
+}
+
+void LX200Basic::handleError(ISwitchVectorProperty *svp, int err, const char *msg)
+{
+
+ svp->s = IPS_ALERT;
+
+ /* First check to see if the telescope is connected */
+ if (testTelescope())
+ {
+ /* The telescope is off locally */
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_BUSY;
+ IDSetSwitch(&PowerSP, "Telescope is not responding to commands, will retry in 10 seconds.");
+
+ IDSetSwitch(svp, NULL);
+ IEAddTimer(10000, retryConnection, NULL);
+ return;
+ }
+
+ /* If the error is a time out, then the device doesn't support this property or busy*/
+ if (err == -2)
+ {
+ svp->s = IPS_ALERT;
+ IDSetSwitch(svp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
+ }
+ else
+ /* Changing property failed, user should retry. */
+ IDSetSwitch( svp , "%s failed.", msg);
+
+ fault = true;
+}
+
+void LX200Basic::handleError(INumberVectorProperty *nvp, int err, const char *msg)
+{
+
+ nvp->s = IPS_ALERT;
+
+ /* First check to see if the telescope is connected */
+ if (testTelescope())
+ {
+ /* The telescope is off locally */
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_BUSY;
+ IDSetSwitch(&PowerSP, "Telescope is not responding to commands, will retry in 10 seconds.");
+
+ IDSetNumber(nvp, NULL);
+ IEAddTimer(10000, retryConnection, NULL);
+ return;
+ }
+
+ /* If the error is a time out, then the device doesn't support this property */
+ if (err == -2)
+ {
+ nvp->s = IPS_ALERT;
+ IDSetNumber(nvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
+ }
+ else
+ /* Changing property failed, user should retry. */
+ IDSetNumber( nvp , "%s failed.", msg);
+
+ fault = true;
+}
+
+void LX200Basic::handleError(ITextVectorProperty *tvp, int err, const char *msg)
+{
+
+ tvp->s = IPS_ALERT;
+
+ /* First check to see if the telescope is connected */
+ if (testTelescope())
+ {
+ /* The telescope is off locally */
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_BUSY;
+ IDSetSwitch(&PowerSP, "Telescope is not responding to commands, will retry in 10 seconds.");
+
+ IDSetText(tvp, NULL);
+ IEAddTimer(10000, retryConnection, NULL);
+ return;
+ }
+
+ /* If the error is a time out, then the device doesn't support this property */
+ if (err == -2)
+ {
+ tvp->s = IPS_ALERT;
+ IDSetText(tvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
+ }
+
+ else
+ /* Changing property failed, user should retry. */
+ IDSetText( tvp , "%s failed.", msg);
+
+ fault = true;
+}
+
+ void LX200Basic::correctFault()
+ {
+
+ fault = false;
+ IDMessage(mydev, "Telescope is online.");
+
+ }
+
+bool LX200Basic::isTelescopeOn(void)
+{
+ if (simulation) return true;
+
+ return (PowerSP.sp[0].s == ISS_ON);
+}
+
+static void retryConnection(void * p)
+{
+ p=p;
+
+ if (testTelescope())
+ telescope->connectionLost();
+ else
+ telescope->connectionResumed();
+}
+
+void LX200Basic::ISPoll()
+{
+ double dx, dy;
+ int err=0;
+
+ if (!isTelescopeOn())
+ return;
+
+ switch (EqNP.s)
+ {
+ case IPS_IDLE:
+ getLX200RA(&currentRA);
+ getLX200DEC(&currentDEC);
+
+ if ( fabs (currentRA - lastRA) > 0.01 || fabs (currentDEC - lastDEC) > 0.01)
+ {
+ lastRA = currentRA;
+ lastDEC = currentDEC;
+ IDSetNumber (&EqNP, NULL);
+ }
+ break;
+
+ case IPS_BUSY:
+ getLX200RA(&currentRA);
+ getLX200DEC(&currentDEC);
+ dx = targetRA - currentRA;
+ dy = targetDEC - currentDEC;
+
+ IDLog("targetRA is %g, currentRA is %g\n", targetRA, currentRA);
+ IDLog("targetDEC is %g, currentDEC is %g\n*************************\n", targetDEC, currentDEC);
+
+ // Wait until acknowledged or within threshold
+ if (fabs(dx) <= RA_THRESHOLD && fabs(dy) <= DEC_THRESHOLD)
+ {
+
+ lastRA = currentRA;
+ lastDEC = currentDEC;
+ IUResetSwitches(&OnCoordSetSP);
+ OnCoordSetSP.s = IPS_OK;
+ EqNP.s = IPS_OK;
+ IDSetNumber (&EqNP, NULL);
+
+ switch (currentSet)
+ {
+ case LX200_SLEW:
+ OnCoordSetSP.sp[0].s = ISS_ON;
+ IDSetSwitch (&OnCoordSetSP, "Slew is complete.");
+ break;
+
+ case LX200_TRACK:
+ OnCoordSetSP.sp[1].s = ISS_ON;
+ IDSetSwitch (&OnCoordSetSP, "Slew is complete. Tracking...");
+ break;
+
+ case LX200_SYNC:
+ break;
+ }
+
+ } else
+ IDSetNumber (&EqNP, NULL);
+ break;
+
+ case IPS_OK:
+
+ if ( (err = getLX200RA(&currentRA)) < 0 || (err = getLX200DEC(&currentDEC)) < 0)
+ {
+ handleError(&EqNP, err, "Getting RA/DEC");
+ return;
+ }
+
+ if (fault)
+ correctFault();
+
+ if ( (currentRA != lastRA) || (currentDEC != lastDEC))
+ {
+ lastRA = currentRA;
+ lastDEC = currentDEC;
+ IDSetNumber (&EqNP, NULL);
+ }
+ break;
+
+
+ case IPS_ALERT:
+ break;
+ }
+
+}
+
+void LX200Basic::getBasicData()
+{
+ // Get current RA/DEC
+ getLX200RA(&currentRA);
+ getLX200DEC(&currentDEC);
+ targetRA = currentRA;
+ targetDEC = currentDEC;
+
+ IDSetNumber (&EqNP, NULL);
+}
+
+int LX200Basic::handleCoordSet()
+{
+
+ int err;
+ char syncString[256];
+ char RAStr[32], DecStr[32];
+ double dx, dy;
+
+ switch (currentSet)
+ {
+
+ // Slew
+ case LX200_SLEW:
+ lastSet = LX200_SLEW;
+ if (EqNP.s == IPS_BUSY)
+ {
+ IDLog("Aboring Slew\n");
+ abortSlew();
+
+ // sleep for 100 mseconds
+ usleep(100000);
+ }
+
+ if ((err = Slew()))
+ {
+ slewError(err);
+ return (-1);
+ }
+
+ EqNP.s = IPS_BUSY;
+ fs_sexa(RAStr, targetRA, 2, 3600);
+ fs_sexa(DecStr, targetDEC, 2, 3600);
+ IDSetNumber(&EqNP, "Slewing to JNow RA %s - DEC %s", RAStr, DecStr);
+ IDLog("Slewing to JNow RA %s - DEC %s\n", RAStr, DecStr);
+ break;
+
+ // Track
+ case LX200_TRACK:
+ IDLog("We're in LX200_TRACK\n");
+ if (EqNP.s == IPS_BUSY)
+ {
+ IDLog("Aboring Slew\n");
+ abortSlew();
+
+ // sleep for 200 mseconds
+ usleep(200000);
+ }
+
+ dx = fabs ( targetRA - currentRA );
+ dy = fabs (targetDEC - currentDEC);
+
+
+ if (dx >= TRACKING_THRESHOLD || dy >= TRACKING_THRESHOLD)
+ {
+ IDLog("Exceeded Tracking threshold, will attempt to slew to the new target.\n");
+ IDLog("targetRA is %g, currentRA is %g\n", targetRA, currentRA);
+ IDLog("targetDEC is %g, currentDEC is %g\n*************************\n", targetDEC, currentDEC);
+
+ if ((err = Slew()))
+ {
+ slewError(err);
+ return (-1);
+ }
+
+ fs_sexa(RAStr, targetRA, 2, 3600);
+ fs_sexa(DecStr, targetDEC, 2, 3600);
+ EqNP.s = IPS_BUSY;
+ IDSetNumber(&EqNP, "Slewing to JNow RA %s - DEC %s", RAStr, DecStr);
+ IDLog("Slewing to JNow RA %s - DEC %s\n", RAStr, DecStr);
+ }
+ else
+ {
+ IDLog("Tracking called, but tracking threshold not reached yet.\n");
+ EqNP.s = IPS_OK;
+ EqNP.np[0].value = currentRA;
+ EqNP.np[1].value = currentDEC;
+
+ if (lastSet != LX200_TRACK)
+ IDSetNumber(&EqNP, "Tracking...");
+ else
+ IDSetNumber(&EqNP, NULL);
+ }
+ lastSet = LX200_TRACK;
+ break;
+
+ // Sync
+ case LX200_SYNC:
+ lastSet = LX200_SYNC;
+ EqNP.s = IPS_IDLE;
+
+ if ( ( err = Sync(syncString) < 0) )
+ {
+ IDSetNumber( &EqNP , "Synchronization failed.");
+ return (-1);
+ }
+
+ EqNP.s = IPS_OK;
+ IDLog("Synchronization successful %s\n", syncString);
+ IDSetNumber(&EqNP, "Synchronization successful.");
+ break;
+ }
+
+ return (0);
+
+}
+
+int LX200Basic::getOnSwitch(ISwitchVectorProperty *sp)
+{
+ for (int i=0; i < sp->nsp ; i++)
+ if (sp->sp[i].s == ISS_ON)
+ return i;
+
+ return -1;
+}
+
+
+int LX200Basic::checkPower(ISwitchVectorProperty *sp)
+{
+ if (simulation) return 0;
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(sp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", sp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", sp->label);
+
+ sp->s = IPS_IDLE;
+ IDSetSwitch(sp, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int LX200Basic::checkPower(INumberVectorProperty *np)
+{
+ if (simulation) return 0;
+
+ if (PowerSP.s != IPS_OK)
+ {
+
+ if (!strcmp(np->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", np->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", np->label);
+
+ np->s = IPS_IDLE;
+ IDSetNumber(np, NULL);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+int LX200Basic::checkPower(ITextVectorProperty *tp)
+{
+
+ if (simulation) return 0;
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(tp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", tp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the telescope is offline.", tp->label);
+
+ tp->s = IPS_IDLE;
+ IDSetText(tp, NULL);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+void LX200Basic::powerTelescope()
+{
+ switch (PowerSP.sp[0].s)
+ {
+ case ISS_ON:
+
+ if (simulation)
+ {
+ PowerSP.s = IPS_OK;
+ IDSetSwitch (&PowerSP, "Simulated telescope is online.");
+ return;
+ }
+
+ if (Connect(PortT[0].text))
+ {
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch (&PowerSP, "Error connecting to port %s\n", PortT[0].text);
+ return;
+ }
+
+ if (testTelescope())
+ {
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch (&PowerSP, "Error connecting to Telescope. Telescope is offline.");
+ return;
+ }
+
+ IDLog("telescope test successfful\n");
+ PowerSP.s = IPS_OK;
+ IDSetSwitch (&PowerSP, "Telescope is online. Retrieving basic data...");
+ getBasicData();
+ break;
+
+ case ISS_OFF:
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_IDLE;
+ if (simulation)
+ {
+ IDSetSwitch (&PowerSP, "Simulated Telescope is offline.");
+ return;
+ }
+ IDSetSwitch (&PowerSP, "Telescope is offline.");
+ IDLog("Telescope is offline.");
+
+ Disconnect();
+ break;
+
+ }
+
+}
+
+void LX200Basic::slewError(int slewCode)
+{
+ OnCoordSetSP.s = IPS_IDLE;
+
+ if (slewCode == 1)
+ IDSetSwitch (&OnCoordSetSP, "Object below horizon.");
+ else if (slewCode == 2)
+ IDSetSwitch (&OnCoordSetSP, "Object below the minimum elevation limit.");
+ else
+ IDSetSwitch (&OnCoordSetSP, "Slew failed.");
+
+
+}
+
+void LX200Basic::enableSimulation(bool enable)
+{
+ simulation = enable;
+
+ if (simulation)
+ IDLog("Warning: Simulation is activated.\n");
+ else
+ IDLog("Simulation is disabled.\n");
+}
+
+void LX200Basic::connectionLost()
+{
+ PowerSP.s = IPS_IDLE;
+ IDSetSwitch(&PowerSP, "The connection to the telescope is lost.");
+ return;
+
+}
+
+void LX200Basic::connectionResumed()
+{
+ PowerS[0].s = ISS_ON;
+ PowerS[1].s = ISS_OFF;
+ PowerSP.s = IPS_OK;
+
+ IDSetSwitch(&PowerSP, "The connection to the telescope has been resumed.");
+}
+
+
diff --git a/kstars/kstars/indi/lx200basic.h b/kstars/kstars/indi/lx200basic.h
new file mode 100644
index 00000000..8e9917d6
--- /dev/null
+++ b/kstars/kstars/indi/lx200basic.h
@@ -0,0 +1,109 @@
+/*
+ LX200 Basic Driver
+ Copyright (C) 2005 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef LX200BASIC_H
+#define LX200BASIC_H
+
+#include "indidevapi.h"
+#include "indicom.h"
+
+#define POLLMS 1000 /* poll period, ms */
+#define mydev "LX200 Basic" /* The device name */
+
+
+
+class LX200Basic
+{
+ public:
+ LX200Basic();
+ ~LX200Basic();
+
+ void ISGetProperties (const char *dev);
+ void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+ void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+ void ISPoll ();
+
+ void connectionLost();
+ void connectionResumed();
+
+private:
+
+ void initProperties();
+
+ /* Switches */
+ ISwitch PowerS[2];
+ ISwitch OnCoordSetS[3];
+ ISwitch AbortSlewS[1];
+
+ /* Texts */
+ IText PortT[1];
+ IText ObjectT[1];
+
+ /* Numbers */
+ INumber EqN[2];
+
+ /* Switch Vectors */
+ ISwitchVectorProperty PowerSP;
+ ISwitchVectorProperty OnCoordSetSP;
+ ISwitchVectorProperty AbortSlewSP;
+
+ /* Number Vectors */
+ INumberVectorProperty EqNP;
+
+ /* Text Vectors */
+ ITextVectorProperty PortTP;
+ ITextVectorProperty ObjectTP;
+
+ void getBasicData();
+ int checkPower(INumberVectorProperty *np);
+ int checkPower(ISwitchVectorProperty *sp);
+ int checkPower(ITextVectorProperty *tp);
+ void handleError(ISwitchVectorProperty *svp, int err, const char *msg);
+ void handleError(INumberVectorProperty *nvp, int err, const char *msg);
+ void handleError(ITextVectorProperty *tvp, int err, const char *msg);
+ bool isTelescopeOn(void);
+ void powerTelescope();
+ void slewError(int slewCode);
+ int handleCoordSet();
+ int getOnSwitch(ISwitchVectorProperty *sp);
+ void correctFault();
+ void enableSimulation(bool enable);
+
+
+ protected:
+
+ double JD;
+ double targetRA;
+ double targetDEC;
+ double lastRA;
+ double lastDEC;
+ double UTCOffset;
+ bool simulation;
+ bool fault;
+
+ struct tm *localTM;
+
+ int currentSet;
+ int lastSet;
+
+};
+
+#endif
diff --git a/kstars/kstars/indi/lx200classic.cpp b/kstars/kstars/indi/lx200classic.cpp
new file mode 100644
index 00000000..5788bd16
--- /dev/null
+++ b/kstars/kstars/indi/lx200classic.cpp
@@ -0,0 +1,333 @@
+/*
+ LX200 Classoc
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lx200classic.h"
+#include "lx200driver.h"
+
+extern LX200Generic *telescope;
+extern INumberVectorProperty eqNum;
+extern ITextVectorProperty Time;
+extern int MaxReticleFlashRate;
+
+#define BASIC_GROUP "Main Control"
+#define LIBRARY_GROUP "Library"
+#define MOVE_GROUP "Movement Control"
+
+static IText ObjectText[] = {{"objectText", "Info", 0, 0, 0, 0}};
+static ITextVectorProperty ObjectInfo = {mydev, "Object Info", "", BASIC_GROUP, IP_RO, 0, IPS_IDLE, ObjectText, NARRAY(ObjectText), "", 0};
+
+/* Library group */
+static ISwitch StarCatalogS[] = {{"STAR", "", ISS_ON, 0, 0}, {"SAO", "", ISS_OFF, 0, 0}, {"GCVS", "", ISS_OFF, 0, 0}};
+static ISwitch DeepSkyCatalogS[] = {{"NGC", "", ISS_ON, 0, 0}, {"IC", "", ISS_OFF, 0, 0}, {"UGC", "", ISS_OFF, 0, 0}, {"Caldwell", "", ISS_OFF, 0, 0}, {"Arp", "", ISS_OFF, 0, 0}, {"Abell", "", ISS_OFF, 0, 0}, {"Messier", "", ISS_OFF, 0, 0}};
+static ISwitch SolarS[] = { {"Select", "Select item...", ISS_ON, 0, 0}, {"1", "Mercury", ISS_OFF,0 , 0}, {"2", "Venus", ISS_OFF, 0, 0}, {"3", "Moon", ISS_OFF, 0, 0}, {"4", "Mars", ISS_OFF, 0, 0}, {"5", "Jupiter", ISS_OFF, 0, 0}, {"6", "Saturn", ISS_OFF, 0, 0}, {"7", "Uranus", ISS_OFF, 0, 0}, {"8", "Neptune", ISS_OFF, 0, 0}, {"9", "Pluto", ISS_OFF, 0 ,0}};
+
+static ISwitchVectorProperty StarCatalogSw = { mydev, "Star Catalogs", "", LIBRARY_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, StarCatalogS, NARRAY(StarCatalogS), "", 0};
+static ISwitchVectorProperty DeepSkyCatalogSw= { mydev, "Deep Sky Catalogs", "", LIBRARY_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, DeepSkyCatalogS, NARRAY(DeepSkyCatalogS), "", 0};
+static ISwitchVectorProperty SolarSw = { mydev, "SOLAR_SYSTEM", "Solar System", LIBRARY_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, SolarS, NARRAY(SolarS), "", 0};
+
+static INumber ObjectN[] = { "ObjectN", "Number", "%g", 1., 10000., 1., 0., 0, 0, 0};
+static INumberVectorProperty ObjectNo= { mydev, "Object Number", "", LIBRARY_GROUP, IP_RW, 0, IPS_IDLE, ObjectN, NARRAY(ObjectN), "", 0 };
+
+static INumber MaxSlew[] = {{"maxSlew", "Rate", "%g", 2.0, 9.0, 1.0, 9., 0, 0 ,0}};
+static INumberVectorProperty MaxSlewRate = { mydev, "Max slew Rate", "", MOVE_GROUP, IP_RW, 0, IPS_IDLE, MaxSlew, NARRAY(MaxSlew), "", 0};
+
+static INumber altLimit[] = {
+ {"minAlt", "min Alt", "%+03f", -90., 90., 0., 0., 0, 0, 0},
+ {"maxAlt", "max Alt", "%+03f", -90., 90., 0., 0., 0, 0, 0}};
+static INumberVectorProperty elevationLimit = { mydev, "altLimit", "Slew elevation Limit", BASIC_GROUP, IP_RW, 0, IPS_IDLE, altLimit, NARRAY(altLimit), "", 0};
+
+void changeLX200ClassicDeviceName(const char *newName)
+{
+ strcpy(ObjectInfo.device, newName);
+ strcpy(SolarSw.device, newName);
+ strcpy(StarCatalogSw.device, newName);
+ strcpy(DeepSkyCatalogSw.device, newName);
+ strcpy(ObjectNo.device, newName);
+ strcpy(MaxSlewRate.device , newName );
+ strcpy(elevationLimit.device , newName );
+}
+
+LX200Classic::LX200Classic() : LX200Generic()
+{
+ ObjectInfo.tp[0].text = new char[128];
+ strcpy(ObjectInfo.tp[0].text, "");
+
+ currentCatalog = LX200_STAR_C;
+ currentSubCatalog = 0;
+
+}
+
+
+void LX200Classic::ISGetProperties (const char *dev)
+{
+
+if (dev && strcmp (thisDevice, dev))
+ return;
+
+ LX200Generic::ISGetProperties(dev);
+
+ IDDefNumber (&elevationLimit, NULL);
+ IDDefText (&ObjectInfo, NULL);
+ IDDefSwitch (&SolarSw, NULL);
+ IDDefSwitch (&StarCatalogSw, NULL);
+ IDDefSwitch (&DeepSkyCatalogSw, NULL);
+ IDDefNumber (&ObjectNo, NULL);
+ IDDefNumber (&MaxSlewRate, NULL);
+
+}
+
+void LX200Classic::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+ // ignore if not ours //
+ if (strcmp (dev, thisDevice))
+ return;
+
+ LX200Generic::ISNewText (dev, name, texts, names, n);
+}
+
+
+void LX200Classic::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ int err=0;
+
+ // ignore if not ours //
+ if (strcmp (dev, thisDevice))
+ return;
+
+ if ( !strcmp (name, ObjectNo.name) )
+ {
+ if (checkPower(&ObjectNo))
+ return;
+
+ selectCatalogObject( currentCatalog, (int) values[0]);
+
+ getLX200RA(&eqNum.np[0].value);
+ getLX200DEC(&eqNum.np[1].value);
+
+ ObjectNo.s = eqNum.s = IPS_OK;
+ IDSetNumber(&ObjectNo , "Object updated");
+ IDSetNumber(&eqNum, NULL);
+
+ if (getObjectInfo(ObjectText[0].text) < 0)
+ IDMessage(thisDevice, "Getting object info failed.");
+ else
+ IDSetText (&ObjectInfo, NULL);
+
+ handleCoordSet();
+
+ return;
+ }
+
+ if ( !strcmp (name, MaxSlewRate.name) )
+ {
+
+ if (checkPower(&MaxSlewRate))
+ return;
+
+ if ( ( err = setMaxSlewRate( (int) values[0]) < 0) )
+ {
+ handleError(&MaxSlewRate, err, "Setting maximum slew rate");
+ return;
+ }
+ MaxSlewRate.s = IPS_OK;
+ MaxSlewRate.np[0].value = values[0];
+ IDSetNumber(&MaxSlewRate, NULL);
+ return;
+ }
+
+
+
+ if (!strcmp (name, elevationLimit.name))
+ {
+ // new elevation limits
+ double minAlt = 0, maxAlt = 0;
+ int i, nset;
+
+ if (checkPower(&elevationLimit))
+ return;
+
+ for (nset = i = 0; i < n; i++)
+ {
+ INumber *altp = IUFindNumber (&elevationLimit, names[i]);
+ if (altp == &altLimit[0])
+ {
+ minAlt = values[i];
+ nset += minAlt >= -90.0 && minAlt <= 90.0;
+ } else if (altp == &altLimit[1])
+ {
+ maxAlt = values[i];
+ nset += maxAlt >= -90.0 && maxAlt <= 90.0;
+ }
+ }
+ if (nset == 2)
+ {
+ //char l[32], L[32];
+ if ( ( err = setMinElevationLimit( (int) minAlt) < 0) )
+ {
+ handleError(&elevationLimit, err, "Setting elevation limit");
+ }
+ setMaxElevationLimit( (int) maxAlt);
+ elevationLimit.np[0].value = minAlt;
+ elevationLimit.np[1].value = maxAlt;
+ elevationLimit.s = IPS_OK;
+ IDSetNumber (&elevationLimit, NULL);
+ } else
+ {
+ elevationLimit.s = IPS_IDLE;
+ IDSetNumber(&elevationLimit, "elevation limit missing or invalid");
+ }
+
+ return;
+ }
+
+ LX200Generic::ISNewNumber (dev, name, values, names, n);
+}
+
+ void LX200Classic::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+ {
+
+ int index=0;
+
+ // ignore if not ours //
+ if (strcmp (dev, thisDevice))
+ return;
+
+ // Star Catalog
+ if (!strcmp (name, StarCatalogSw.name))
+ {
+ if (checkPower(&StarCatalogSw))
+ return;
+
+ IUResetSwitches(&StarCatalogSw);
+ IUUpdateSwitches(&StarCatalogSw, states, names, n);
+ index = getOnSwitch(&StarCatalogSw);
+
+ currentCatalog = LX200_STAR_C;
+
+ if (selectSubCatalog(currentCatalog, index))
+ {
+ currentSubCatalog = index;
+ StarCatalogSw.s = IPS_OK;
+ IDSetSwitch(&StarCatalogSw, NULL);
+ }
+ else
+ {
+ StarCatalogSw.s = IPS_IDLE;
+ IDSetSwitch(&StarCatalogSw, "Catalog unavailable");
+ }
+ return;
+ }
+
+ // Deep sky catalog
+ if (!strcmp (name, DeepSkyCatalogSw.name))
+ {
+ if (checkPower(&DeepSkyCatalogSw))
+ return;
+
+ IUResetSwitches(&DeepSkyCatalogSw);
+ IUUpdateSwitches(&DeepSkyCatalogSw, states, names, n);
+ index = getOnSwitch(&DeepSkyCatalogSw);
+
+ if (index == LX200_MESSIER_C)
+ {
+ currentCatalog = index;
+ DeepSkyCatalogSw.s = IPS_OK;
+ IDSetSwitch(&DeepSkyCatalogSw, NULL);
+ return;
+ }
+ else
+ currentCatalog = LX200_DEEPSKY_C;
+
+ if (selectSubCatalog(currentCatalog, index))
+ {
+ currentSubCatalog = index;
+ DeepSkyCatalogSw.s = IPS_OK;
+ IDSetSwitch(&DeepSkyCatalogSw, NULL);
+ }
+ else
+ {
+ DeepSkyCatalogSw.s = IPS_IDLE;
+ IDSetSwitch(&DeepSkyCatalogSw, "Catalog unavailable");
+ }
+ return;
+ }
+
+ // Solar system
+ if (!strcmp (name, SolarSw.name))
+ {
+
+ if (checkPower(&SolarSw))
+ return;
+
+ IUResetSwitches(&SolarSw);
+ IUUpdateSwitches(&SolarSw, states, names, n);
+ index = getOnSwitch(&SolarSw);
+
+ // We ignore the first option : "Select item"
+ if (index == 0)
+ {
+ SolarSw.s = IPS_IDLE;
+ IDSetSwitch(&SolarSw, NULL);
+ return;
+ }
+
+ selectSubCatalog ( LX200_STAR_C, LX200_STAR);
+ selectCatalogObject( LX200_STAR_C, index + 900);
+
+ ObjectNo.s = IPS_OK;
+ SolarSw.s = IPS_OK;
+
+ getObjectInfo(ObjectInfo.tp[0].text);
+ IDSetNumber(&ObjectNo , "Object updated.");
+ IDSetSwitch(&SolarSw, NULL);
+
+ if (currentCatalog == LX200_STAR_C || currentCatalog == LX200_DEEPSKY_C)
+ selectSubCatalog( currentCatalog, currentSubCatalog);
+
+ getObjectRA(&targetRA);
+ getObjectDEC(&targetDEC);
+
+ handleCoordSet();
+
+ return;
+ }
+
+ LX200Generic::ISNewSwitch (dev, name, states, names, n);
+
+ }
+
+ void LX200Classic::ISPoll ()
+ {
+
+ LX200Generic::ISPoll();
+
+ }
+
+ void LX200Classic::getBasicData()
+ {
+
+ // process parent first
+ LX200Generic::getBasicData();
+
+ }
diff --git a/kstars/kstars/indi/lx200classic.h b/kstars/kstars/indi/lx200classic.h
new file mode 100644
index 00000000..e76d8d63
--- /dev/null
+++ b/kstars/kstars/indi/lx200classic.h
@@ -0,0 +1,49 @@
+/*
+ LX200 Classic
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef LX200CLASSIC_H
+#define LX200CLASSIC_H
+
+#include "lx200generic.h"
+
+class LX200Classic : public LX200Generic
+{
+ public:
+ LX200Classic();
+ ~LX200Classic() {}
+
+ void ISGetProperties (const char *dev);
+ void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+ void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+ void ISPoll ();
+ void getBasicData();
+
+ private:
+ int currentCatalog;
+ int currentSubCatalog;
+
+
+};
+
+void changeLX200ClassicDeviceName(const char *newName);
+
+#endif
+
diff --git a/kstars/kstars/indi/lx200driver.c b/kstars/kstars/indi/lx200driver.c
new file mode 100644
index 00000000..9c521cfe
--- /dev/null
+++ b/kstars/kstars/indi/lx200driver.c
@@ -0,0 +1,1386 @@
+#if 0
+ LX200 Driver
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <time.h>
+
+#include "indicom.h"
+#include "indidevapi.h"
+#include "lx200driver.h"
+
+#define LX200_TIMEOUT 5 /* FD timeout in seconds */
+
+int fd;
+int read_ret, write_ret;
+
+/**************************************************************************
+ Basic I/O
+**************************************************************************/
+int openPort(const char *portID);
+int portRead(char *buf, int nbytes, int timeout);
+int portWrite(const char * buf);
+int LX200readOut(int timeout);
+
+int Connect(const char* device);
+void Disconnect(void);
+
+/**************************************************************************
+ Diagnostics
+ **************************************************************************/
+char ACK(void);
+int testTelescope(void);
+int testAP(void);
+
+/**************************************************************************
+ Get Commands: store data in the supplied buffer. Return 0 on success or -1 on failure
+ **************************************************************************/
+
+/* Get Double from Sexagisemal */
+int getCommandSexa(double *value, const char *cmd);
+/* Get String */
+int getCommandString(char *data, const char* cmd);
+/* Get Int */
+int getCommandInt(int *value, const char* cmd);
+/* Get tracking frequency */
+int getTrackFreq(double * value);
+/* Get site Latitude */
+int getSiteLatitude(int *dd, int *mm);
+/* Get site Longitude */
+int getSiteLongitude(int *ddd, int *mm);
+/* Get Calender data */
+int getCalenderDate(char *date);
+/* Get site Name */
+int getSiteName(char *siteName, int siteNum);
+/* Get Number of Bars */
+int getNumberOfBars(int *value);
+/* Get Home Search Status */
+int getHomeSearchStatus(int *status);
+/* Get OTA Temperature */
+int getOTATemp(double * value);
+/* Get time format: 12 or 24 */
+int getTimeFormat(int *format);
+
+
+/**************************************************************************
+ Set Commands
+ **************************************************************************/
+
+/* Set Int */
+int setCommandInt(int data, const char *cmd);
+/* Set Sexigesimal */
+int setCommandXYZ( int x, int y, int z, const char *cmd);
+/* Common routine for Set commands */
+int setStandardProcedure(char * writeData);
+/* Set Slew Mode */
+int setSlewMode(int slewMode);
+/* Set Alignment mode */
+int setAlignmentMode(unsigned int alignMode);
+/* Set Object RA */
+int setObjectRA(double ra);
+/* set Object DEC */
+int setObjectDEC(double dec);
+/* Set Calender date */
+int setCalenderDate(int dd, int mm, int yy);
+/* Set UTC offset */
+int setUTCOffset(double hours);
+/* Set Track Freq */
+int setTrackFreq(double trackF);
+/* Set current site longitude */
+int setSiteLongitude(double Long);
+/* Set current site latitude */
+int setSiteLatitude(double Lat);
+/* Set Object Azimuth */
+int setObjAz(double az);
+/* Set Object Altitude */
+int setObjAlt(double alt);
+/* Set site name */
+int setSiteName(char * siteName, int siteNum);
+/* Set maximum slew rate */
+int setMaxSlewRate(int slewRate);
+/* Set focuser motion */
+int setFocuserMotion(int motionType);
+/* Set focuser speed mode */
+int setFocuserSpeedMode (int speedMode);
+/* Set minimum elevation limit */
+int setMinElevationLimit(int min);
+/* Set maximum elevation limit */
+int setMaxElevationLimit(int max);
+
+/**************************************************************************
+ Motion Commands
+ **************************************************************************/
+/* Slew to the selected coordinates */
+int Slew(void);
+/* Synchronize to the selected coordinates and return the matching object if any */
+int Sync(char *matchedObject);
+/* Abort slew in all axes */
+int abortSlew(void);
+/* Move into one direction, two valid directions can be stacked */
+int MoveTo(int direction);
+/* Half movement in a particular direction */
+int HaltMovement(int direction);
+/* Select the tracking mode */
+int selectTrackingMode(int trackMode);
+/* Select Astro-Physics tracking mode */
+int selectAPTrackingMode(int trackMode);
+
+/**************************************************************************
+ Other Commands
+ **************************************************************************/
+ /* Ensures LX200 RA/DEC format is long */
+int checkLX200Format(void);
+/* Select a site from the LX200 controller */
+int selectSite(int siteNum);
+/* Select a catalog object */
+int selectCatalogObject(int catalog, int NNNN);
+/* Select a sub catalog */
+int selectSubCatalog(int catalog, int subCatalog);
+
+/**********************************************************************
+* BASIC
+**********************************************************************/
+
+int Connect(const char *device)
+{
+ fprintf(stderr, "Connecting to device %s\n", device);
+
+ if (openPort(device) < 0)
+ return -1;
+ else
+ return 0;
+}
+
+void Disconnect()
+{
+fprintf(stderr, "Disconnected.\n");
+close(fd);
+}
+
+int testTelescope()
+{
+ int i=0;
+ char ack[1] = { (char) 0x06 };
+ char MountAlign[64];
+ fprintf(stderr, "Testing telescope's connection...\n");
+
+ for (i=0; i < 2; i++)
+ {
+ write(fd, ack, 1);
+ read_ret = portRead(MountAlign, 1, LX200_TIMEOUT);
+ if (read_ret == 1)
+ return 0;
+ usleep(50000);
+ }
+
+ return -1;
+}
+
+int testAP()
+{
+ int i=0;
+ char currentDate[64];
+
+ fprintf(stderr, "Testing telescope's connection...\n");
+
+ /* We need to test if the telescope is responding
+ / We're going to request the calander date */
+ for (i=0; i < 2; i++)
+ {
+ if (!getCalenderDate(currentDate))
+ return 0;
+
+ usleep(50000);
+ }
+
+ return -1;
+
+}
+
+
+/**********************************************************************
+* GET
+**********************************************************************/
+
+char ACK()
+{
+ char ack[1] = { (char) 0x06 };
+ char MountAlign[2];
+
+ write_ret = write(fd, ack, 1);
+
+ if (write_ret < 0)
+ return -1;
+
+ read_ret = portRead(MountAlign, 1, LX200_TIMEOUT);
+
+ if (read_ret == 1)
+ return MountAlign[0];
+ else
+ return read_ret;
+
+}
+
+int getCommandSexa(double *value, const char * cmd)
+{
+ char tempString[16];
+
+ tcflush(fd, TCIFLUSH);
+
+ if (portWrite(cmd) < 0)
+ return -1;
+
+ if ( (read_ret = portRead(tempString, -1, LX200_TIMEOUT)) < 1)
+ return read_ret;
+
+ tempString[read_ret - 1] = '\0';
+
+ if (f_scansexa(tempString, value))
+ {
+ fprintf(stderr, "unable to process [%s]\n", tempString);
+ return -1;
+ }
+
+ return 0;
+}
+
+int getCommandString(char *data, const char* cmd)
+{
+ char * term;
+
+ if (portWrite(cmd) < 0)
+ return -1;
+
+ read_ret = portRead(data, -1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ term = strchr (data, '#');
+ if (term)
+ *term = '\0';
+
+ fprintf(stderr, "Requested data: %s\n", data);
+
+ return 0;
+}
+
+int getCalenderDate(char *date)
+{
+
+ int dd, mm, yy;
+ int err;
+
+ if ( (err = getCommandString(date, "#:GC#")) )
+ return err;
+
+ /* Meade format is MM/DD/YY */
+
+ read_ret = sscanf(date, "%d%*c%d%*c%d", &mm, &dd, &yy);
+ if (read_ret < 3)
+ return -1;
+
+ /* We need to have in in YYYY/MM/DD format */
+ sprintf(date, "20%02d/%02d/%02d", yy, mm, dd);
+
+ return (0);
+
+}
+
+int getTimeFormat(int *format)
+{
+ char tempString[16];
+ int tMode;
+
+ if (portWrite("#:Gc#") < 0)
+ return -1;
+
+ read_ret = portRead(tempString, -1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ tempString[read_ret-1] = '\0';
+
+ read_ret = sscanf(tempString, "(%d)", &tMode);
+
+ if (read_ret < 1)
+ return -1;
+ else
+ *format = tMode;
+
+ return 0;
+
+}
+
+/*int getUTCOffset()
+{
+ char tempString[4];
+ int offSet;
+
+ portWrite("#:GG#");
+
+ read_ret = portRead(tempString, 4);
+ if (read_ret)
+ return -1;
+
+ tempString[3] = '\0';
+
+ sscanf(tempString, "%d", &offSet);
+
+ fprintf(stderr, "UTC Offset: %d\n", offSet);
+
+ return offSet;
+}
+
+int getMaxElevationLimit()
+{
+ char tempString[16];
+ int limit;
+
+ portWrite("#:Go#");
+
+ read_ret = portRead(tempString, -1, LX200_TIMEOUT);
+ if (read_ret < 1)
+ return -1;
+
+ tempString[read_ret-1] = '\0';
+
+ sscanf(tempString, "%d", &limit);
+
+ fprintf(stderr, "Max elevation limit string is %s\n", tempString);
+
+ return limit;
+}
+
+int getMinElevationLimit()
+{
+ char tempString[16];
+ int limit;
+
+ portWrite("#:Gh#");
+
+ read_ret = portRead(tempString, -1, LX200_TIMEOUT);
+ if (read_ret < 1)
+ return -1;
+
+ tempString[read_ret-1] = '\0';
+
+ sscanf(tempString, "%d", &limit);
+
+ fprintf(stderr, "Min elevation limit string is %s\n", tempString);
+
+ return limit;
+
+}
+*/
+
+int getSiteName(char *siteName, int siteNum)
+{
+ char * term;
+
+ switch (siteNum)
+ {
+ case 1:
+ if (portWrite("#:GM#") < 0)
+ return -1;
+ break;
+ case 2:
+ if (portWrite("#:GN#") < 0)
+ return -1;
+ break;
+ case 3:
+ if (portWrite("#:GO#") < 0)
+ return -1;
+ break;
+ case 4:
+ if (portWrite("#:GP#") < 0)
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+
+ read_ret = portRead(siteName, -1, LX200_TIMEOUT);
+ if (read_ret < 1)
+ return read_ret;
+
+ siteName[read_ret - 1] = '\0';
+
+ term = strchr (siteName, ' ');
+ if (term)
+ *term = '\0';
+
+ term = strchr (siteName, '<');
+ if (term)
+ strcpy(siteName, "unused site");
+
+ fprintf(stderr, "Requested site name: %s\n", siteName);
+
+ return 0;
+}
+
+int getSiteLatitude(int *dd, int *mm)
+{
+ char tempString[16];
+
+ if (portWrite("#:Gt#") < 0)
+ return -1;
+
+ read_ret = portRead(tempString, -1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ tempString[read_ret -1] = '\0';
+
+ if (sscanf (tempString, "%d%*c%d", dd, mm) < 2)
+ return -1;
+
+ fprintf(stderr, "Requested site latitude in String %s\n", tempString);
+ fprintf(stderr, "Requested site latitude %d:%d\n", *dd, *mm);
+
+ return 0;
+}
+
+int getSiteLongitude(int *ddd, int *mm)
+{
+ char tempString[16];
+
+ if (portWrite("#:Gg#") < 0)
+ return -1;
+
+ read_ret = portRead(tempString, -1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ tempString[read_ret -1] = '\0';
+
+ if (sscanf (tempString, "%d%*c%d", ddd, mm) < 2)
+ return -1;
+
+ fprintf(stderr, "Requested site longitude in String %s\n", tempString);
+ fprintf(stderr, "Requested site longitude %d:%d\n", *ddd, *mm);
+
+ return 0;
+}
+
+int getTrackFreq(double *value)
+{
+ float Freq;
+ char tempString[16];
+
+ if (portWrite("#:GT#") < 0)
+ return -1;
+
+ read_ret = portRead(tempString, -1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ tempString[read_ret] = '\0';
+
+ /*fprintf(stderr, "Telescope tracking freq str: %s\n", tempString);*/
+
+ if (sscanf(tempString, "%f#", &Freq) < 1)
+ return -1;
+
+ *value = (double) Freq;
+
+ /*fprintf(stderr, "Tracking frequency value is %f\n", Freq);*/
+
+ return 0;
+}
+
+int getNumberOfBars(int *value)
+{
+ char tempString[128];
+
+ if (portWrite("#:D#") < 0)
+ return -1;
+
+ read_ret = portRead(tempString, -1, LX200_TIMEOUT);
+
+ if (read_ret < 0)
+ return read_ret;
+
+ *value = read_ret -1;
+
+ return 0;
+}
+
+int getHomeSearchStatus(int *status)
+{
+ char tempString[16];
+
+ if (portWrite("#:h?#") < 0)
+ return -1;
+
+ read_ret = portRead(tempString, 1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ tempString[1] = '\0';
+
+ if (tempString[0] == '0')
+ *status = 0;
+ else if (tempString[0] == '1')
+ *status = 1;
+ else if (tempString[0] == '2')
+ *status = 1;
+
+ return 0;
+}
+
+int getOTATemp(double *value)
+{
+
+ char tempString[16];
+ float temp;
+
+ if (portWrite("#:fT#") < 0)
+ return -1;
+
+ read_ret = portRead(tempString, -1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ tempString[read_ret - 1] = '\0';
+
+ if (sscanf(tempString, "%f", &temp) < 1)
+ return -1;
+
+ *value = (double) temp;
+
+ return 0;
+
+}
+
+int updateSkyCommanderCoord(double *ra, double *dec)
+{
+ char coords[16];
+ char CR[1] = { (char) 0x0D };
+ float RA=0.0, DEC=0.0;
+
+ write(fd, CR, 1);
+
+ read_ret = portRead(coords, 16, LX200_TIMEOUT);
+
+ read_ret = sscanf(coords, " %g %g", &RA, &DEC);
+
+ if (read_ret < 2)
+ {
+ fprintf(stderr, "Error in Sky commander number format [%s], exiting.\n", coords);
+ return -1;
+ }
+
+ *ra = RA;
+ *dec = DEC;
+
+ return 0;
+
+}
+
+
+/**********************************************************************
+* SET
+**********************************************************************/
+
+int setStandardProcedure(char * data)
+{
+ char boolRet[2];
+
+ if (portWrite(data) < 0)
+ return -1;
+
+ read_ret = portRead(boolRet, 1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ if (boolRet[0] == '0')
+ {
+ fprintf(stderr, "%s Failed.\n", data);
+ return -1;
+ }
+
+ fprintf(stderr, "%s Successful\n", data);
+ return 0;
+
+
+}
+
+int setCommandInt(int data, const char *cmd)
+{
+
+ char tempString[16];
+
+ snprintf(tempString, sizeof( tempString ), "%s%d#", cmd, data);
+
+ if (portWrite(tempString) < 0)
+ return -1;
+
+ return 0;
+}
+
+int setMinElevationLimit(int min)
+{
+ char tempString[16];
+
+ snprintf(tempString, sizeof( tempString ), "#:Sh%02d#", min);
+
+ return (setStandardProcedure(tempString));
+}
+
+int setMaxElevationLimit(int max)
+{
+ char tempString[16];
+
+ snprintf(tempString, sizeof( tempString ), "#:So%02d*#", max);
+
+ return (setStandardProcedure(tempString));
+
+}
+
+int setMaxSlewRate(int slewRate)
+{
+
+ char tempString[16];
+
+ if (slewRate < 2 || slewRate > 8)
+ return -1;
+
+ snprintf(tempString, sizeof( tempString ), "#:Sw%d#", slewRate);
+
+ return (setStandardProcedure(tempString));
+
+}
+
+
+int setObjectRA(double ra)
+{
+
+ int h, m, s;
+ char tempString[16];
+
+ getSexComponents(ra, &h, &m, &s);
+
+ snprintf(tempString, sizeof( tempString ), "#:Sr %02d:%02d:%02d#", h, m, s);
+ IDLog("Set Object RA String %s\n", tempString);
+ return (setStandardProcedure(tempString));
+}
+
+
+int setObjectDEC(double dec)
+{
+ int d, m, s;
+ char tempString[16];
+
+ getSexComponents(dec, &d, &m, &s);
+
+ /* case with negative zero */
+ if (!d && dec < 0)
+ snprintf(tempString, sizeof( tempString ), "#:Sd -%02d:%02d:%02d#", d, m, s);
+ else
+ snprintf(tempString, sizeof( tempString ), "#:Sd %+03d:%02d:%02d#", d, m, s);
+
+ IDLog("Set Object DEC String %s\n", tempString);
+
+ return (setStandardProcedure(tempString));
+
+}
+
+int setCommandXYZ(int x, int y, int z, const char *cmd)
+{
+ char tempString[16];
+
+ snprintf(tempString, sizeof( tempString ), "%s %02d:%02d:%02d#", cmd, x, y, z);
+
+ return (setStandardProcedure(tempString));
+}
+
+int setAlignmentMode(unsigned int alignMode)
+{
+ fprintf(stderr , "Set alignment mode %d\n", alignMode);
+
+ switch (alignMode)
+ {
+ case LX200_ALIGN_POLAR:
+ if (portWrite("#:AP#") < 0)
+ return -1;
+ break;
+ case LX200_ALIGN_ALTAZ:
+ if (portWrite("#:AA#") < 0)
+ return -1;
+ break;
+ case LX200_ALIGN_LAND:
+ if (portWrite("#:AL#") < 0)
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+int setCalenderDate(int dd, int mm, int yy)
+{
+ char tempString[32];
+ char dumpPlanetaryUpdateString[64];
+ char boolRet[2];
+ yy = yy % 100;
+
+ snprintf(tempString, sizeof( tempString ), "#:SC %02d/%02d/%02d#", mm, dd, yy);
+
+ if (portWrite(tempString) < 0)
+ return -1;
+
+ read_ret = portRead(boolRet, 1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ boolRet[1] = '\0';
+
+ if (boolRet[0] == '0')
+ return -1;
+
+ /* Read dumped data */
+ portRead(dumpPlanetaryUpdateString, -1, LX200_TIMEOUT);
+ portRead(dumpPlanetaryUpdateString, -1, 5);
+
+ return 0;
+}
+
+int setUTCOffset(double hours)
+{
+ char tempString[16];
+
+ /*TODO add fractions*/
+ snprintf(tempString, sizeof( tempString ), "#:SG %+03d#", (int) hours);
+
+ fprintf(stderr, "UTC string is %s\n", tempString);
+
+ return (setStandardProcedure(tempString));
+
+}
+
+int setSiteLongitude(double Long)
+{
+ int d, m, s;
+ char tempString[32];
+
+ getSexComponents(Long, &d, &m, &s);
+
+ snprintf(tempString, sizeof( tempString ), "#:Sg%03d:%02d#", d, m);
+
+ return (setStandardProcedure(tempString));
+}
+
+int setSiteLatitude(double Lat)
+{
+ int d, m, s;
+ char tempString[32];
+
+ getSexComponents(Lat, &d, &m, &s);
+
+ snprintf(tempString, sizeof( tempString ), "#:St%+03d:%02d:%02d#", d, m, s);
+
+ return (setStandardProcedure(tempString));
+}
+
+int setObjAz(double az)
+{
+ int d,m,s;
+ char tempString[16];
+
+ getSexComponents(az, &d, &m, &s);
+
+ snprintf(tempString, sizeof( tempString ), "#:Sz%03d:%02d#", d, m);
+
+ return (setStandardProcedure(tempString));
+
+}
+
+int setObjAlt(double alt)
+{
+ int d, m, s;
+ char tempString[16];
+
+ getSexComponents(alt, &d, &m, &s);
+
+ snprintf(tempString, sizeof( tempString ), "#:Sa%+02d*%02d#", d, m);
+
+ return (setStandardProcedure(tempString));
+}
+
+
+int setSiteName(char * siteName, int siteNum)
+{
+
+ char tempString[16];
+
+ switch (siteNum)
+ {
+ case 1:
+ snprintf(tempString, sizeof( tempString ), "#:SM %s#", siteName);
+ break;
+ case 2:
+ snprintf(tempString, sizeof( tempString ), "#:SN %s#", siteName);
+ break;
+ case 3:
+ snprintf(tempString, sizeof( tempString ), "#:SO %s#", siteName);
+ break;
+ case 4:
+ snprintf(tempString, sizeof( tempString ), "#:SP %s#", siteName);
+ break;
+ default:
+ return -1;
+ }
+
+ return (setStandardProcedure(tempString));
+}
+
+int setSlewMode(int slewMode)
+{
+
+ switch (slewMode)
+ {
+ case LX200_SLEW_MAX:
+ if (portWrite("#:RS#") < 0)
+ return -1;
+ break;
+ case LX200_SLEW_FIND:
+ if (portWrite("#:RM#") < 0)
+ return -1;
+ break;
+ case LX200_SLEW_CENTER:
+ if (portWrite("#:RC#") < 0)
+ return -1;
+ break;
+ case LX200_SLEW_GUIDE:
+ if (portWrite("#:RG#") < 0)
+ return -1;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+
+}
+
+int setFocuserMotion(int motionType)
+{
+
+ switch (motionType)
+ {
+ case LX200_FOCUSIN:
+ if (portWrite("#:F+#") < 0)
+ return -1;
+ break;
+ case LX200_FOCUSOUT:
+ if (portWrite("#:F-#") < 0)
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+int setFocuserSpeedMode (int speedMode)
+{
+
+ switch (speedMode)
+ {
+ case LX200_HALTFOCUS:
+ if (portWrite("#:FQ#") < 0)
+ return -1;
+ break;
+ case LX200_FOCUSSLOW:
+ if (portWrite("#:FS#") < 0)
+ return -1;
+ break;
+ case LX200_FOCUSMEDIUM:
+ if (portWrite("#:F3#") < 0)
+ return -1;
+ break;
+ case LX200_FOCUSFAST:
+ if (portWrite("#:FF#") < 0)
+ return -1;
+ break;
+ }
+
+ return 0;
+
+}
+
+int setTrackFreq(double trackF)
+{
+ char tempString[16];
+
+ snprintf(tempString, sizeof( tempString ), "#:ST %04.1f#", trackF);
+
+ return (setStandardProcedure(tempString));
+
+}
+
+/**********************************************************************
+* Misc
+*********************************************************************/
+
+int Slew()
+{
+ char slewNum[2];
+ char errorMsg[128];
+
+ if (portWrite("#:MS#") < 0)
+ return -1;
+
+ read_ret = portRead(slewNum, 1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ slewNum[1] = '\0';
+
+ if (slewNum[0] == '0')
+ return 0;
+
+ read_ret = portRead(errorMsg, -1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ if (slewNum[0] == '1')
+ return 1;
+ else return 2;
+
+}
+
+int MoveTo(int direction)
+{
+
+ switch (direction)
+ {
+ case LX200_NORTH:
+ portWrite("#:Mn#");
+ break;
+ case LX200_WEST:
+ portWrite("#:Mw#");
+ break;
+ case LX200_EAST:
+ portWrite("#:Me#");
+ break;
+ case LX200_SOUTH:
+ portWrite("#:Ms#");
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int HaltMovement(int direction)
+{
+
+switch (direction)
+ {
+ case LX200_NORTH:
+ if (portWrite("#:Qn#") < 0)
+ return -1;
+ break;
+ case LX200_WEST:
+ if (portWrite("#:Qw#") < 0)
+ return -1;
+ break;
+ case LX200_EAST:
+ if (portWrite("#:Qe#") < 0)
+ return -1;
+ break;
+ case LX200_SOUTH:
+ if (portWrite("#:Qs#") < 0)
+ return -1;
+ break;
+ case LX200_ALL:
+ if (portWrite("#:Q#") < 0)
+ return -1;
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ return 0;
+
+}
+
+int abortSlew()
+{
+ if (portWrite("#:Q#") < 0)
+ return -1;
+
+ return 0;
+}
+
+int Sync(char *matchedObject)
+{
+ portWrite("#:CM#");
+
+ read_ret = portRead(matchedObject, -1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ matchedObject[read_ret-1] = '\0';
+
+ /* Sleep 10ms before flushing. This solves some issues with LX200 compatible devices. */
+ usleep(10000);
+
+ tcflush(fd, TCIFLUSH);
+
+ return 0;
+}
+
+int selectSite(int siteNum)
+{
+
+ switch (siteNum)
+ {
+ case 1:
+ if (portWrite("#:W1#") < 0)
+ return -1;
+ break;
+ case 2:
+ if (portWrite("#:W2#") < 0)
+ return -1;
+ break;
+ case 3:
+ if (portWrite("#:W3#") < 0)
+ return -1;
+ break;
+ case 4:
+ if (portWrite("#:W4#") < 0)
+ return -1;
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ return 0;
+
+}
+
+int selectCatalogObject(int catalog, int NNNN)
+{
+ char tempString[16];
+
+ switch (catalog)
+ {
+ case LX200_STAR_C:
+ snprintf(tempString, sizeof( tempString ), "#:LS%d#", NNNN);
+ break;
+ case LX200_DEEPSKY_C:
+ snprintf(tempString, sizeof( tempString ), "#:LC%d#", NNNN);
+ break;
+ case LX200_MESSIER_C:
+ snprintf(tempString, sizeof( tempString ), "#:LM%d#", NNNN);
+ break;
+ default:
+ return -1;
+ }
+
+ if (portWrite(tempString) < 0)
+ return -1;
+
+ return 0;
+}
+
+int selectSubCatalog(int catalog, int subCatalog)
+{
+ char tempString[16];
+ switch (catalog)
+ {
+ case LX200_STAR_C:
+ snprintf(tempString, sizeof( tempString ), "#:LsD%d#", subCatalog);
+ break;
+ case LX200_DEEPSKY_C:
+ snprintf(tempString, sizeof( tempString ), "#:LoD%d#", subCatalog);
+ break;
+ case LX200_MESSIER_C:
+ return 1;
+ default:
+ return 0;
+ }
+
+ return (setStandardProcedure(tempString));
+}
+
+int checkLX200Format()
+{
+
+ char tempString[16];
+
+ if (portWrite("#:GR#") < 0)
+ return -1;
+
+ read_ret = portRead(tempString, -1, LX200_TIMEOUT);
+
+ if (read_ret < 1)
+ return read_ret;
+
+ tempString[read_ret - 1] = '\0';
+
+ /* Short */
+ if (tempString[5] == '.')
+ if (portWrite("#:U#") < 0)
+ return -1;
+
+ return 0;
+}
+
+int selectTrackingMode(int trackMode)
+{
+
+ switch (trackMode)
+ {
+ case LX200_TRACK_DEFAULT:
+ fprintf(stderr, "Setting tracking mode to sidereal.\n");
+ if (portWrite("#:TQ#") < 0)
+ return -1;
+ break;
+ case LX200_TRACK_LUNAR:
+ fprintf(stderr, "Setting tracking mode to LUNAR.\n");
+ if (portWrite("#:TL#") < 0)
+ return -1;
+ break;
+ case LX200_TRACK_MANUAL:
+ fprintf(stderr, "Setting tracking mode to CUSTOM.\n");
+ if (portWrite("#:TM#") < 0)
+ return -1;
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ return 0;
+
+}
+
+int selectAPTrackingMode(int trackMode)
+{
+ switch (trackMode)
+ {
+ /* Lunar */
+ case 0:
+ fprintf(stderr, "Setting tracking mode to lunar.\n");
+ if (portWrite("#:RT0#") < 0)
+ return -1;
+ break;
+
+ /* Solar */
+ case 1:
+ fprintf(stderr, "Setting tracking mode to solar.\n");
+ if (portWrite("#:RT1#") < 0)
+ return -1;
+ break;
+
+ /* Sidereal */
+ case 2:
+ fprintf(stderr, "Setting tracking mode to sidereal.\n");
+ if (portWrite("#:RT2#") < 0)
+ return -1;
+ break;
+
+ /* Zero */
+ case 3:
+ fprintf(stderr, "Setting tracking mode to zero.\n");
+ if (portWrite("#:RT9#") < 0)
+ return -1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ return 0;
+
+}
+
+
+/**********************************************************************
+* Comm
+**********************************************************************/
+
+int openPort(const char *portID)
+{
+ struct termios ttyOptions;
+
+ if ( (fd = open(portID, O_RDWR)) == -1)
+ return -1;
+
+ memset(&ttyOptions, 0, sizeof(ttyOptions));
+ tcgetattr(fd, &ttyOptions);
+
+ /* Control options
+ charecter size */
+ ttyOptions.c_cflag &= ~CSIZE;
+ /* 8 bit, enable read */
+ ttyOptions.c_cflag |= CREAD | CLOCAL | CS8;
+ /* no parity */
+ ttyOptions.c_cflag &= ~PARENB;
+
+ /* set baud rate */
+ cfsetispeed(&ttyOptions, B9600);
+ cfsetospeed(&ttyOptions, B9600);
+
+ /* set input/output flags */
+ ttyOptions.c_iflag = IGNBRK;
+ /* no software flow control */
+ ttyOptions.c_iflag &= ~(IXON|IXOFF|IXANY);
+
+ /* Read at least one byte */
+ ttyOptions.c_cc[VMIN] = 1;
+ ttyOptions.c_cc[VTIME] = 5;
+
+ /* Misc. */
+ ttyOptions.c_lflag = 0;
+ ttyOptions.c_oflag = 0;
+
+ /* set attributes */
+ tcsetattr(fd, TCSANOW, &ttyOptions);
+
+ /* flush the channel */
+ tcflush(fd, TCIOFLUSH);
+ return (fd);
+}
+
+int portWrite(const char * buf)
+{
+ int nbytes, totalBytesWritten;
+ int bytesWritten = 0;
+
+ nbytes = totalBytesWritten = strlen(buf);
+
+ while (nbytes > 0)
+ {
+
+ bytesWritten = write(fd, buf, nbytes);
+
+ if (bytesWritten < 0)
+ return -1;
+
+ buf += bytesWritten;
+ nbytes -= bytesWritten;
+ }
+
+ /* Returns the # of bytes written */
+ return (totalBytesWritten);
+}
+
+int portRead(char *buf, int nbytes, int timeout)
+{
+
+int bytesRead = 0;
+int totalBytesRead = 0;
+int err;
+
+ /* Loop until encountring the '#' char */
+ if (nbytes == -1)
+ {
+ for (;;)
+ {
+ if ( (err = LX200readOut(timeout)) )
+ return err;
+
+ bytesRead = read(fd, buf, 1);
+
+ if (bytesRead < 0 )
+ return -1;
+
+ if (bytesRead)
+ totalBytesRead++;
+
+ if (*buf == '#')
+ return totalBytesRead;
+
+ buf += bytesRead;
+ }
+ }
+
+ while (nbytes > 0)
+ {
+ if ( (err = LX200readOut(timeout)) )
+ return err;
+
+ bytesRead = read(fd, buf, nbytes);
+
+ if (bytesRead < 0 )
+ return -1;
+
+ buf += bytesRead;
+ totalBytesRead++;
+ nbytes -= bytesRead;
+ }
+
+ return totalBytesRead;
+}
+
+int LX200readOut(int timeout)
+{
+ struct timeval tv;
+ fd_set readout;
+ int retval;
+
+ FD_ZERO(&readout);
+ FD_SET(fd, &readout);
+
+ /* wait for 'timeout' seconds */
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ /* Wait till we have a change in the fd status */
+ retval = select (fd+1, &readout, NULL, NULL, &tv);
+
+ /* Return 0 on successful fd change */
+ if (retval > 0)
+ return 0;
+ /* Return -1 due to an error */
+ else if (retval == -1)
+ return retval;
+ /* Return -2 if time expires before anything interesting happens */
+ else
+ return -2;
+
+}
+
diff --git a/kstars/kstars/indi/lx200driver.h b/kstars/kstars/indi/lx200driver.h
new file mode 100644
index 00000000..06b8017f
--- /dev/null
+++ b/kstars/kstars/indi/lx200driver.h
@@ -0,0 +1,247 @@
+/*
+ LX200 Driver
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef LX200DRIVER_H
+#define LX200DRIVER_H
+
+ /* Slew speeds */
+enum TSlew { LX200_SLEW_MAX, LX200_SLEW_FIND, LX200_SLEW_CENTER, LX200_SLEW_GUIDE};
+ /* Alignment modes */
+enum TAlign { LX200_ALIGN_POLAR, LX200_ALIGN_ALTAZ, LX200_ALIGN_LAND };
+ /* Directions */
+enum TDirection { LX200_NORTH, LX200_WEST, LX200_EAST, LX200_SOUTH, LX200_ALL};
+ /* Formats of Right ascention and Declenation */
+enum TFormat { LX200_FORMAT_SHORT, LX200_FORMAT_LONG};
+ /* Time Format */
+enum TTimeFormat { LX200_24, LX200_AM, LX200_PM};
+ /* Focus operation */
+enum TFocusMotion { LX200_FOCUSIN, LX200_FOCUSOUT };
+enum TFocusSpeed { LX200_HALTFOCUS = 0, LX200_FOCUSFAST, LX200_FOCUSMEDIUM, LX200_FOCUSSLOW };
+ /* Library catalogs */
+enum TCatalog { LX200_STAR_C, LX200_DEEPSKY_C};
+ /* Frequency mode */
+enum StarCatalog { LX200_STAR, LX200_SAO, LX200_GCVS };
+ /* Deep Sky Catalogs */
+enum DeepSkyCatalog { LX200_NGC, LX200_IC, LX200_UGC, LX200_CALDWELL, LX200_ARP, LX200_ABELL, LX200_MESSIER_C};
+ /* Mount tracking frequency, in Hz */
+enum TFreq { LX200_TRACK_DEFAULT, LX200_TRACK_LUNAR, LX200_TRACK_MANUAL};
+
+#define MaxReticleDutyCycle 15
+#define MaxFocuserSpeed 4
+
+/* GET formatted sexagisemal value from device, return as double */
+#define getLX200RA(x) getCommandSexa(x, "#:GR#")
+#define getLX200DEC(x) getCommandSexa(x, "#:GD#")
+#define getObjectRA(x) getCommandSexa(x, "#:Gr#")
+#define getObjectDEC(x) getCommandSexa(x, "#:Gd#")
+#define getLocalTime12(x) getCommandSexa(x, "#:Ga#")
+#define getLocalTime24(x) getCommandSexa(x, "#:GL#")
+#define getSDTime(x) getCommandSexa(x, "#:GS#")
+#define getLX200Alt(x) getCommandSexa(x, "#:GA#")
+#define getLX200Az(x) getCommandSexa(x, "#:GZ#")
+
+/* GET String from device and store in supplied buffer x */
+#define getObjectInfo(x) getCommandString(x, "#:LI#")
+#define getVersionDate(x) getCommandString(x, "#:GVD#")
+#define getVersionTime(x) getCommandString(x, "#:GVT#")
+#define getFullVersion(x) getCommandString(x, "#:GVF#")
+#define getVersionNumber(x) getCommandString(x, "#:GVN#")
+#define getProductName(x) getCommandString(x, "#:GVP#")
+#define turnGPS_StreamOn() getCommandString(x, "#:gps#")
+
+/* GET Int from device and store in supplied pointer to integer x */
+#define getUTCOffset(x) getCommandInt(x, "#:GG#")
+#define getMaxElevationLimit(x) getCommandInt(x, "#:Go#")
+#define getMinElevationLimit(x) getCommandInt(x, "#:Gh#")
+
+/* Generic set, x is an integer */
+#define setReticleDutyFlashCycle(x) setCommandInt(x, "#:BD")
+#define setReticleFlashRate(x) setCommandInt(x, "#:B")
+#define setFocuserSpeed(x) setCommandInt(x, "#:F")
+#define setSlewSpeed(x) setCommandInt(x, "#:Sw")
+
+/* Set X:Y:Z */
+#define setLocalTime(x,y,z) setCommandXYZ(x,y,z, "#:SL")
+#define setSDTime(x,y,z) setCommandXYZ(x,y,z, "#:SS")
+
+/* GPS Specefic */
+#define turnGPSOn() portWrite("#:g+#")
+#define turnGPSOff() portWrite("#:g-#")
+#define alignGPSScope() portWrite("#:Aa#")
+#define gpsSleep() portWrite("#:hN#")
+#define gpsWakeUp() portWrite("#:hW#")
+#define gpsRestart() portWrite("#:I#")
+#define updateGPS_System() setStandardProcedure("#:gT#")
+#define enableDecAltPec() portWrite("#:QA+#")
+#define disableDecAltPec() portWrite("#:QA-#")
+#define enableRaAzPec() portWrite("#:QZ+#")
+#define disableRaAzPec() portWrite("#:QZ-#")
+#define activateAltDecAntiBackSlash() portWrite("#$BAdd#")
+#define activateAzRaAntiBackSlash() portWrite("#$BZdd#")
+#define SelenographicSync() portWrite("#:CL#")
+
+#define slewToAltAz() setStandardProcedure("#:MA#")
+#define toggleTimeFormat() portWrite("#:H#")
+#define increaseReticleBrightness() portWrite("#:B+#")
+#define decreaseReticleBrightness() portWrite("#:B-#")
+#define turnFanOn() portWrite("#:f+#")
+#define turnFanOff() portWrite("#:f-#")
+#define seekHomeAndSave() portWrite("#:hS#")
+#define seekHomeAndSet() portWrite("#:hF#")
+#define turnFieldDeRotatorOn() portWrite("#:r+#")
+#define turnFieldDeRotatorOff() portWrite("#:r-#")
+#define slewToPark() portWrite("#:hP#")
+
+/* Astro-Physics specific */
+#define APPark() portWrite("#:KA#")
+#define APUnpark() portWrite("#:PO#");
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**************************************************************************
+ Basic I/O
+**************************************************************************/
+int openPort(const char *portID);
+int portRead(char *buf, int nbytes, int timeout);
+int portWrite(const char * buf);
+int LX200readOut(int timeout);
+
+int Connect(const char* device);
+void Disconnect();
+
+/**************************************************************************
+ Diagnostics
+ **************************************************************************/
+char ACK();
+int testTelescope();
+int testAP();
+
+/**************************************************************************
+ Get Commands: store data in the supplied buffer. Return 0 on success or -1 on failure
+ **************************************************************************/
+
+/* Get Double from Sexagisemal */
+int getCommandSexa(double *value, const char *cmd);
+/* Get String */
+int getCommandString(char *data, const char* cmd);
+/* Get Int */
+int getCommandInt(int *value, const char* cmd);
+/* Get tracking frequency */
+int getTrackFreq(double * value);
+/* Get site Latitude */
+int getSiteLatitude(int *dd, int *mm);
+/* Get site Longitude */
+int getSiteLongitude(int *ddd, int *mm);
+/* Get Calender data */
+int getCalenderDate(char *date);
+/* Get site Name */
+int getSiteName(char *siteName, int siteNum);
+/* Get Number of Bars */
+int getNumberOfBars(int *value);
+/* Get Home Search Status */
+int getHomeSearchStatus(int *status);
+/* Get OTA Temperature */
+int getOTATemp(double * value);
+/* Get time format: 12 or 24 */
+int getTimeFormat(int *format);
+/* Get RA, DEC from Sky Commander controller */
+int updateSkyCommanderCoord(double *ra, double *dec);
+/**************************************************************************
+ Set Commands
+ **************************************************************************/
+
+/* Set Int */
+int setCommandInt(int data, const char *cmd);
+/* Set Sexigesimal */
+int setCommandXYZ( int x, int y, int z, const char *cmd);
+/* Common routine for Set commands */
+int setStandardProcedure(char * writeData);
+/* Set Slew Mode */
+int setSlewMode(int slewMode);
+/* Set Alignment mode */
+int setAlignmentMode(unsigned int alignMode);
+/* Set Object RA */
+int setObjectRA(double ra);
+/* set Object DEC */
+int setObjectDEC(double dec);
+/* Set Calender date */
+int setCalenderDate(int dd, int mm, int yy);
+/* Set UTC offset */
+int setUTCOffset(double hours);
+/* Set Track Freq */
+int setTrackFreq(double trackF);
+/* Set current site longitude */
+int setSiteLongitude(double Long);
+/* Set current site latitude */
+int setSiteLatitude(double Lat);
+/* Set Object Azimuth */
+int setObjAz(double az);
+/* Set Object Altitude */
+int setObjAlt(double alt);
+/* Set site name */
+int setSiteName(char * siteName, int siteNum);
+/* Set maximum slew rate */
+int setMaxSlewRate(int slewRate);
+/* Set focuser motion */
+int setFocuserMotion(int motionType);
+/* Set focuser speed mode */
+int setFocuserSpeedMode (int speedMode);
+/* Set minimum elevation limit */
+int setMinElevationLimit(int min);
+/* Set maximum elevation limit */
+int setMaxElevationLimit(int max);
+
+/**************************************************************************
+ Motion Commands
+ **************************************************************************/
+/* Slew to the selected coordinates */
+int Slew();
+/* Synchronize to the selected coordinates and return the matching object if any */
+int Sync(char *matchedObject);
+/* Abort slew in all axes */
+int abortSlew();
+/* Move into one direction, two valid directions can be stacked */
+int MoveTo(int direction);
+/* Half movement in a particular direction */
+int HaltMovement(int direction);
+/* Select the tracking mode */
+int selectTrackingMode(int trackMode);
+/* Select Astro-Physics tracking mode */
+int selectAPTrackingMode(int trackMode);
+
+/**************************************************************************
+ Other Commands
+ **************************************************************************/
+ /* Ensures LX200 RA/DEC format is long */
+int checkLX200Format();
+/* Select a site from the LX200 controller */
+int selectSite(int siteNum);
+/* Select a catalog object */
+int selectCatalogObject(int catalog, int NNNN);
+/* Select a sub catalog */
+int selectSubCatalog(int catalog, int subCatalog);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/kstars/kstars/indi/lx200generic.cpp b/kstars/kstars/indi/lx200generic.cpp
new file mode 100644
index 00000000..b4f6d792
--- /dev/null
+++ b/kstars/kstars/indi/lx200generic.cpp
@@ -0,0 +1,2033 @@
+#if 0
+ LX200 Generic
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "indicom.h"
+#include "lx200driver.h"
+#include "lx200gps.h"
+#include "lx200classic.h"
+
+/*
+** Return the timezone offset in hours (as a double, so fractional
+** hours are possible, for instance in Newfoundland). Also sets
+** daylight on non-Linux systems to record whether DST is in effect.
+*/
+
+
+#if !(TIMEZONE_IS_INT)
+static int daylight = 0;
+#endif
+
+static inline double timezoneOffset()
+{
+/*
+** In Linux, there's a timezone variable that holds the timezone offset;
+** Otherwise, we need to make a little detour. The directions of the offset
+** are different: CET is -3600 in Linux and +3600 elsewhere.
+*/
+#if TIMEZONE_IS_INT
+ return timezone / (60 * 60);
+#else
+ time_t now;
+ struct tm *tm;
+ now = time(NULL);
+ tm = localtime(&now);
+ daylight = tm->tm_isdst;
+ return -(tm->tm_gmtoff) / (60 * 60);
+#endif
+}
+
+LX200Generic *telescope = NULL;
+int MaxReticleFlashRate = 3;
+
+/* There is _one_ binary for all LX200 drivers, but each binary is renamed
+** to its device name (i.e. lx200gps, lx200_16..etc). The main function will
+** fetch from std args the binary name and ISInit will create the apporpiate
+** device afterwards. If the binary name does not match any known devices,
+** we simply create a generic device
+*/
+extern char* me;
+
+#define COMM_GROUP "Communication"
+#define BASIC_GROUP "Main Control"
+#define MOVE_GROUP "Movement Control"
+#define DATETIME_GROUP "Date/Time"
+#define SITE_GROUP "Site Management"
+#define FOCUS_GROUP "Focus Control"
+
+#define RA_THRESHOLD 0.01
+#define DEC_THRESHOLD 0.05
+#define LX200_SLEW 0
+#define LX200_TRACK 1
+#define LX200_SYNC 2
+#define LX200_PARK 3
+
+static void ISPoll(void *);
+static void retryConnection(void *);
+
+/*INDI controls */
+static ISwitch PowerS[] = {{"CONNECT" , "Connect" , ISS_OFF, 0, 0},{"DISCONNECT", "Disconnect", ISS_ON, 0, 0}};
+static ISwitch AlignmentS [] = {{"Polar", "", ISS_ON, 0, 0}, {"AltAz", "", ISS_OFF, 0, 0}, {"Land", "", ISS_OFF, 0, 0}};
+static ISwitch SitesS[] = {{"Site 1", "", ISS_ON, 0, 0}, {"Site 2", "", ISS_OFF, 0, 0}, {"Site 3", "", ISS_OFF, 0, 0}, {"Site 4", "", ISS_OFF, 0 ,0}};
+static ISwitch SlewModeS[] = {{"Max", "", ISS_ON, 0, 0}, {"Find", "", ISS_OFF, 0, 0}, {"Centering", "", ISS_OFF, 0, 0}, {"Guide", "", ISS_OFF, 0 , 0}};
+static ISwitch OnCoordSetS[] = {{"SLEW", "Slew", ISS_ON, 0, 0 }, {"TRACK", "Track", ISS_OFF, 0, 0}, {"SYNC", "Sync", ISS_OFF, 0 , 0}};
+static ISwitch TrackModeS[] = {{ "Default", "", ISS_ON, 0, 0} , { "Lunar", "", ISS_OFF, 0, 0}, {"Manual", "", ISS_OFF, 0, 0}};
+static ISwitch abortSlewS[] = {{"ABORT", "Abort", ISS_OFF, 0, 0 }};
+static ISwitch ParkS[] = { {"PARK", "Park", ISS_OFF, 0, 0} };
+
+static ISwitch MovementS[] = {{"N", "North", ISS_OFF, 0, 0}, {"W", "West", ISS_OFF, 0, 0}, {"E", "East", ISS_OFF, 0, 0}, {"S", "South", ISS_OFF, 0, 0}};
+
+static INumber FocusSpeedN[] = {{"SPEED", "Speed", "%0.f", 0., 3., 1., 0.}};
+static ISwitch FocusMotionS[] = { {"IN", "Focus in", ISS_OFF, 0, 0}, {"OUT", "Focus out", ISS_OFF, 0, 0}};
+static INumber FocusTimerN[] = { {"TIMER", "Timer (s)", "%10.6m", 0., 120., 1., 0., 0, 0, 0 }};
+
+static INumberVectorProperty FocusTimerNP = { mydev, "FOCUS_TIMER", "Focus Timer", FOCUS_GROUP, IP_RW, 0, IPS_IDLE, FocusTimerN, NARRAY(FocusTimerN), "", 0};
+
+/* equatorial position */
+INumber eq[] = {
+ {"RA", "RA H:M:S", "%10.6m", 0., 24., 0., 0., 0, 0, 0},
+ {"DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0., 0, 0, 0},
+};
+//TODO decide appropiate TIME_OUT
+// N.B. No Static identifier as it is needed for external linkage
+INumberVectorProperty eqNum = {
+ mydev, "EQUATORIAL_EOD_COORD", "Equatorial JNow", BASIC_GROUP, IP_RW, 0, IPS_IDLE,
+ eq, NARRAY(eq), "", 0};
+
+/* Fundamental group */
+ISwitchVectorProperty PowerSP = { mydev, "CONNECTION" , "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, PowerS, NARRAY(PowerS), "", 0};
+static IText PortT[] = {{"PORT", "Port", 0, 0, 0, 0}};
+static ITextVectorProperty Port = { mydev, "DEVICE_PORT", "Ports", COMM_GROUP, IP_RW, 0, IPS_IDLE, PortT, NARRAY(PortT), "", 0};
+
+/* Basic data group */
+static ISwitchVectorProperty AlignmentSw = { mydev, "Alignment", "", COMM_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, AlignmentS, NARRAY(AlignmentS), "", 0};
+
+/* Movement group */
+static ISwitchVectorProperty OnCoordSetSw = { mydev, "ON_COORD_SET", "On Set", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, OnCoordSetS, NARRAY(OnCoordSetS), "", 0};
+
+static ISwitchVectorProperty abortSlewSw = { mydev, "ABORT_MOTION", "Abort Slew/Track", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, abortSlewS, NARRAY(abortSlewS), "", 0};
+
+ISwitchVectorProperty ParkSP = {mydev, "PARK", "Park Scope", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, ParkS, NARRAY(ParkS), "", 0 };
+
+static ISwitchVectorProperty SlewModeSw = { mydev, "Slew rate", "", MOVE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, SlewModeS, NARRAY(SlewModeS), "", 0};
+
+static ISwitchVectorProperty TrackModeSw = { mydev, "Tracking Mode", "", MOVE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, TrackModeS, NARRAY(TrackModeS), "", 0};
+
+static INumber TrackFreq[] = {{ "trackFreq", "Freq", "%g", 56.4, 60.1, 0.1, 60.1, 0, 0, 0}};
+
+static INumberVectorProperty TrackingFreq= { mydev, "Tracking Frequency", "", MOVE_GROUP, IP_RW, 0, IPS_IDLE, TrackFreq, NARRAY(TrackFreq), "", 0};
+
+static ISwitchVectorProperty MovementSw = { mydev, "MOVEMENT", "Move toward", MOVE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, MovementS, NARRAY(MovementS), "", 0};
+
+// Focus Control
+static INumberVectorProperty FocusSpeedNP = {mydev, "FOCUS_SPEED", "Speed", FOCUS_GROUP, IP_RW, 0, IPS_IDLE, FocusSpeedN, NARRAY(FocusSpeedN), "", 0};
+
+static ISwitchVectorProperty FocusMotionSw = {mydev, "FOCUS_MOTION", "Motion", FOCUS_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, FocusMotionS, NARRAY(FocusMotionS), "", 0};
+
+/* Data & Time */
+static IText UTC[] = {{"UTC", "UTC", 0, 0, 0, 0}};
+ITextVectorProperty Time = { mydev, "TIME", "UTC Time", DATETIME_GROUP, IP_RW, 0, IPS_IDLE, UTC, NARRAY(UTC), "", 0};
+static INumber STime[] = {{"LST", "Sidereal time", "%10.6m" , 0.,24.,0.,0., 0, 0, 0}};
+INumberVectorProperty SDTime = { mydev, "SDTIME", "Sidereal Time", DATETIME_GROUP, IP_RW, 0, IPS_IDLE, STime, NARRAY(STime), "", 0};
+
+
+/* Site managment */
+static ISwitchVectorProperty SitesSw = { mydev, "Sites", "", SITE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, SitesS, NARRAY(SitesS), "", 0};
+/* geographic location */
+static INumber geo[] = {
+ {"LAT", "Lat. D:M:S +N", "%10.6m", -90., 90., 0., 0., 0, 0, 0},
+ {"LONG", "Long. D:M:S +E", "%10.6m", 0., 360., 0., 0., 0, 0, 0},
+};
+static INumberVectorProperty geoNum = {
+ mydev, "GEOGRAPHIC_COORD", "Geographic Location", SITE_GROUP, IP_RW, 0., IPS_IDLE,
+ geo, NARRAY(geo), "", 0};
+static IText SiteNameT[] = {{"SiteName", "", 0, 0, 0, 0}};
+static ITextVectorProperty SiteName = { mydev, "Site Name", "", SITE_GROUP, IP_RW, 0 , IPS_IDLE, SiteNameT, NARRAY(SiteNameT), "", 0};
+
+void changeLX200GenericDeviceName(const char * newName)
+{
+ strcpy(PowerSP.device , newName);
+ strcpy(Port.device , newName);
+ strcpy(AlignmentSw.device, newName);
+
+ // BASIC_GROUP
+ strcpy(eqNum.device, newName);
+ strcpy(OnCoordSetSw.device , newName );
+ strcpy(abortSlewSw.device , newName );
+ strcpy(ParkSP.device, newName);
+
+ // MOVE_GROUP
+ strcpy(SlewModeSw.device , newName );
+ strcpy(TrackModeSw.device , newName );
+ strcpy(TrackingFreq.device , newName );
+ strcpy(MovementSw.device , newName );
+
+ // FOCUS_GROUP
+ strcpy(FocusSpeedNP.device , newName );
+ strcpy(FocusMotionSw.device , newName );
+ strcpy(FocusTimerNP.device, newName);
+
+ // DATETIME_GROUP
+ strcpy(Time.device , newName );
+ strcpy(SDTime.device , newName );
+
+ // SITE_GROUP
+ strcpy(SitesSw.device , newName );
+ strcpy(SiteName.device , newName );
+ strcpy(geoNum.device , newName );
+
+}
+
+void changeAllDeviceNames(const char *newName)
+{
+ changeLX200GenericDeviceName(newName);
+ changeLX200AutostarDeviceName(newName);
+ changeLX200_16DeviceName(newName);
+ changeLX200ClassicDeviceName(newName);
+ changeLX200GPSDeviceName(newName);
+}
+
+
+/* send client definitions of all properties */
+void ISInit()
+{
+ static int isInit=0;
+
+ if (isInit)
+ return;
+
+ isInit = 1;
+
+ PortT[0].text = strcpy(new char[32], "/dev/ttyS0");
+ UTC[0].text = strcpy(new char[32], "YYYY-MM-DDTHH:MM:SS");
+
+ if (strstr(me, "lx200classic"))
+ {
+ fprintf(stderr , "initilizaing from LX200 classic device...\n");
+ // 1. mydev = device_name
+ changeAllDeviceNames("LX200 Classic");
+ // 2. device = sub_class
+ telescope = new LX200Classic();
+ telescope->setCurrentDeviceName("LX200 Classic");
+
+ MaxReticleFlashRate = 3;
+ }
+
+ else if (strstr(me, "lx200gps"))
+ {
+ fprintf(stderr , "initilizaing from LX200 GPS device...\n");
+ // 1. mydev = device_name
+ changeAllDeviceNames("LX200 GPS");
+ // 2. device = sub_class
+ telescope = new LX200GPS();
+ telescope->setCurrentDeviceName("LX200 GPS");
+
+ MaxReticleFlashRate = 9;
+ }
+ else if (strstr(me, "lx200_16"))
+ {
+
+ IDLog("Initilizaing from LX200 16 device...\n");
+ // 1. mydev = device_name
+ changeAllDeviceNames("LX200 16");
+ // 2. device = sub_class
+ telescope = new LX200_16();
+ telescope->setCurrentDeviceName("LX200 16");
+
+ MaxReticleFlashRate = 3;
+ }
+ else if (strstr(me, "lx200autostar"))
+ {
+ fprintf(stderr , "initilizaing from autostar device...\n");
+
+ // 1. change device name
+ changeAllDeviceNames("LX200 Autostar");
+ // 2. device = sub_class
+ telescope = new LX200Autostar();
+ telescope->setCurrentDeviceName("LX200 Autostar");
+
+ MaxReticleFlashRate = 9;
+ }
+ // be nice and give them a generic device
+ else
+ {
+ telescope = new LX200Generic();
+ telescope->setCurrentDeviceName("LX200 Generic");
+ }
+
+}
+
+void ISGetProperties (const char *dev)
+{ ISInit(); telescope->ISGetProperties(dev); IEAddTimer (POLLMS, ISPoll, NULL);}
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{ ISInit(); telescope->ISNewSwitch(dev, name, states, names, n);}
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{ ISInit(); telescope->ISNewText(dev, name, texts, names, n);}
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{ ISInit(); telescope->ISNewNumber(dev, name, values, names, n);}
+void ISPoll (void *p) { telescope->ISPoll(); IEAddTimer (POLLMS, ISPoll, NULL); p=p;}
+void ISNewBLOB (const char */*dev*/, const char */*name*/, int */*sizes[]*/, char **/*blobs[]*/, char **/*formats[]*/, char **/*names[]*/, int /*n*/)
+{}
+
+/**************************************************
+*** LX200 Generic Implementation
+***************************************************/
+
+LX200Generic::LX200Generic()
+{
+ struct tm *utp;
+ time_t t;
+ time (&t);
+ utp = gmtime (&t);
+
+ currentSiteNum = 1;
+ trackingMode = LX200_TRACK_DEFAULT;
+ lastSet = -1;
+ fault = false;
+ simulation = false;
+ targetRA = 0;
+ targetDEC = 0;
+ currentRA = 0;
+ currentDEC = 0;
+ currentSet = 0;
+ UTCOffset = 0;
+ lastMove[0] = lastMove[1] = lastMove[2] = lastMove[3] = 0;
+
+ localTM = new tm;
+
+ utp->tm_mon += 1;
+ utp->tm_year += 1900;
+ JD = UTtoJD(utp);
+
+ IDLog("Julian Day is %g\n", JD);
+
+ // Children call parent routines, this is the default
+ IDLog("initilizaing from generic LX200 device...\n");
+ IDLog("INDI Version: 2004-02-17\n");
+
+ //enableSimulation(true);
+}
+
+void LX200Generic::setCurrentDeviceName(const char * devName)
+{
+ strcpy(thisDevice, devName);
+
+}
+
+void LX200Generic::ISGetProperties(const char *dev)
+{
+
+ if (dev && strcmp (thisDevice, dev))
+ return;
+
+ // COMM_GROUP
+ IDDefSwitch (&PowerSP, NULL);
+ IDDefText (&Port, NULL);
+ IDDefSwitch (&AlignmentSw, NULL);
+
+ // BASIC_GROUP
+ IDDefNumber (&eqNum, NULL);
+ IDDefSwitch (&OnCoordSetSw, NULL);
+ IDDefSwitch (&abortSlewSw, NULL);
+ IDDefSwitch (&ParkSP, NULL);
+
+ // MOVE_GROUP
+ IDDefNumber (&TrackingFreq, NULL);
+ IDDefSwitch (&SlewModeSw, NULL);
+ IDDefSwitch (&TrackModeSw, NULL);
+ IDDefSwitch (&MovementSw, NULL);
+
+ // FOCUS_GROUP
+ IDDefNumber(&FocusSpeedNP, NULL);
+ IDDefSwitch(&FocusMotionSw, NULL);
+ IDDefNumber(&FocusTimerNP, NULL);
+
+ // DATETIME_GROUP
+ IDDefText (&Time, NULL);
+ IDDefNumber (&SDTime, NULL);
+
+ // SITE_GROUP
+ IDDefSwitch (&SitesSw, NULL);
+ IDDefText (&SiteName, NULL);
+ IDDefNumber (&geoNum, NULL);
+
+ /* Send the basic data to the new client if the previous client(s) are already connected. */
+ if (PowerSP.s == IPS_OK)
+ getBasicData();
+
+}
+
+void LX200Generic::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+ int err;
+ struct tm *ltp = new tm;
+ struct tm utm;
+ time_t ltime;
+ time (&ltime);
+ localtime_r (&ltime, ltp);
+ IText *tp;
+
+ // ignore if not ours //
+ if (strcmp (dev, thisDevice))
+ return;
+
+ // suppress warning
+ n=n;
+
+ if (!strcmp(name, Port.name) )
+ {
+ Port.s = IPS_OK;
+ tp = IUFindText( &Port, names[0] );
+ if (!tp)
+ return;
+
+ tp->text = new char[strlen(texts[0])+1];
+ strcpy(tp->text, texts[0]);
+ IDSetText (&Port, NULL);
+ return;
+ }
+
+ if (!strcmp (name, SiteName.name) )
+ {
+ if (checkPower(&SiteName))
+ return;
+
+ if ( ( err = setSiteName(texts[0], currentSiteNum) < 0) )
+ {
+ handleError(&SiteName, err, "Setting site name");
+ return;
+ }
+ SiteName.s = IPS_OK;
+ tp = IUFindText(&SiteName, names[0]);
+ tp->text = new char[strlen(texts[0])+1];
+ strcpy(tp->text, texts[0]);
+ IDSetText(&SiteName , "Site name updated");
+ return;
+ }
+
+ if (!strcmp (name, Time.name))
+ {
+ if (checkPower(&Time))
+ return;
+
+ if (extractISOTime(texts[0], &utm) < 0)
+ {
+ Time.s = IPS_IDLE;
+ IDSetText(&Time , "Time invalid");
+ return;
+ }
+ ltp->tm_mon += 1;
+ ltp->tm_year += 1900;
+
+
+ /*dayDiff = utm.tm_mday - ltp->tm_mday;
+ if (dayDiff == 0)
+ UTCOffset = (ltp->tm_hour - utm.tm_hour);
+ else if (dayDiff > 0)
+ UTCOffset = ltp->tm_hour - utm.tm_hour - 24;
+ else UTCOffset = ltp->tm_hour - utm.tm_hour + 24;*/
+ tzset();
+
+ UTCOffset = timezoneOffset();
+
+ IDLog("local time is %02d:%02d:%02d\nUTCOffset: %g\n", ltp->tm_hour, ltp->tm_min, ltp->tm_sec, UTCOffset);
+
+ getSDTime(&STime[0].value);
+ IDSetNumber(&SDTime, NULL);
+
+ if ( ( err = setUTCOffset(UTCOffset) < 0) )
+ {
+ Time.s = IPS_IDLE;
+ IDSetText( &Time , "Setting UTC Offset failed.");
+ return;
+ }
+
+ if ( ( err = setLocalTime(ltp->tm_hour, ltp->tm_min, ltp->tm_sec) < 0) )
+ {
+ handleError(&Time, err, "Setting local time");
+ return;
+ }
+
+ tp = IUFindText(&Time, names[0]);
+ if (!tp)
+ return;
+ tp->text = new char[strlen(texts[0])+1];
+ strcpy(tp->text, texts[0]);
+ Time.s = IPS_OK;
+
+ // update JD
+ JD = UTtoJD(&utm);
+
+ utm.tm_mon += 1;
+ utm.tm_year += 1900;
+
+ IDLog("New JD is %f\n", (float) JD);
+
+ if ((localTM->tm_mday == ltp->tm_mday ) && (localTM->tm_mon == ltp->tm_mon) &&
+ (localTM->tm_year == ltp->tm_year))
+ {
+ IDSetText(&Time , "Time updated to %s", texts[0]);
+ return;
+ }
+
+ localTM = ltp;
+
+ if (!strcmp(dev, "LX200 GPS"))
+ {
+ if ( ( err = setCalenderDate(utm.tm_mday, utm.tm_mon, utm.tm_year) < 0) )
+ {
+ handleError(&Time, err, "Setting UTC date.");
+ return;
+ }
+ }
+ else
+ {
+ if ( ( err = setCalenderDate(ltp->tm_mday, ltp->tm_mon, ltp->tm_year) < 0) )
+ {
+ handleError(&Time, err, "Setting local date.");
+ return;
+ }
+ }
+
+ IDSetText(&Time , "Date changed, updating planetary data...");
+ }
+}
+
+
+void LX200Generic::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ int h =0, m =0, s=0, err;
+ double newRA =0, newDEC =0;
+
+ // ignore if not ours //
+ if (strcmp (dev, thisDevice))
+ return;
+
+ if (!strcmp (name, eqNum.name))
+ {
+ int i=0, nset=0;
+
+ if (checkPower(&eqNum))
+ return;
+
+ for (nset = i = 0; i < n; i++)
+ {
+ INumber *eqp = IUFindNumber (&eqNum, names[i]);
+ if (eqp == &eq[0])
+ {
+ newRA = values[i];
+ nset += newRA >= 0 && newRA <= 24.0;
+ } else if (eqp == &eq[1])
+ {
+ newDEC = values[i];
+ nset += newDEC >= -90.0 && newDEC <= 90.0;
+ }
+ }
+
+ if (nset == 2)
+ {
+ /*eqNum.s = IPS_BUSY;*/
+ char RAStr[32], DecStr[32];
+
+ fs_sexa(RAStr, newRA, 2, 3600);
+ fs_sexa(DecStr, newDEC, 2, 3600);
+
+ IDLog("We received J2000 RA %g - DEC %g\n", newRA, newDEC);
+ IDLog("We received J2000 RA %s - DEC %s\n", RAStr, DecStr);
+
+ /*apparentCoord( (double) J2000, JD, &newRA, &newDEC);
+
+ fs_sexa(RAStr, newRA, 2, 3600);
+ fs_sexa(DecStr, newDEC, 2, 3600);
+
+ IDLog("Processed to JNow RA %f - DEC %f\n", newRA, newDEC);
+ IDLog("Processed to JNow RA %s - DEC %s\n", RAStr, DecStr);*/
+
+ if ( (err = setObjectRA(newRA)) < 0 || ( err = setObjectDEC(newDEC)) < 0)
+ {
+ handleError(&eqNum, err, "Setting RA/DEC");
+ return;
+ }
+
+ /*eqNum.s = IPS_BUSY;*/
+ targetRA = newRA;
+ targetDEC = newDEC;
+
+ if (MovementSw.s == IPS_BUSY)
+ {
+ for (int i=0; i < 4; i++)
+ {
+ lastMove[i] = 0;
+ MovementS[i].s = ISS_OFF;
+ }
+
+ MovementSw.s = IPS_IDLE;
+ IDSetSwitch(&MovementSw, NULL);
+ }
+
+ if (handleCoordSet())
+ {
+ eqNum.s = IPS_IDLE;
+ IDSetNumber(&eqNum, NULL);
+
+ }
+ } // end nset
+ else
+ {
+ eqNum.s = IPS_IDLE;
+ IDSetNumber(&eqNum, "RA or Dec missing or invalid");
+ }
+
+ return;
+ } /* end eqNum */
+
+ if ( !strcmp (name, SDTime.name) )
+ {
+ if (checkPower(&SDTime))
+ return;
+
+
+ if (values[0] < 0.0 || values[0] > 24.0)
+ {
+ SDTime.s = IPS_IDLE;
+ IDSetNumber(&SDTime , "Time invalid");
+ return;
+ }
+
+ getSexComponents(values[0], &h, &m, &s);
+ IDLog("Time is %02d:%02d:%02d\n", h, m, s);
+
+ if ( ( err = setSDTime(h, m, s) < 0) )
+ {
+ handleError(&SDTime, err, "Setting siderial time");
+ return;
+ }
+
+ SDTime.np[0].value = values[0];
+ SDTime.s = IPS_OK;
+
+ IDSetNumber(&SDTime , "Sidereal time updated to %02d:%02d:%02d", h, m, s);
+
+ return;
+ }
+
+ if (!strcmp (name, geoNum.name))
+ {
+ // new geographic coords
+ double newLong = 0, newLat = 0;
+ int i, nset;
+ char msg[128];
+
+ if (checkPower(&geoNum))
+ return;
+
+
+ for (nset = i = 0; i < n; i++)
+ {
+ INumber *geop = IUFindNumber (&geoNum, names[i]);
+ if (geop == &geo[0])
+ {
+ newLat = values[i];
+ nset += newLat >= -90.0 && newLat <= 90.0;
+ } else if (geop == &geo[1])
+ {
+ newLong = values[i];
+ nset += newLong >= 0.0 && newLong < 360.0;
+ }
+ }
+
+ if (nset == 2)
+ {
+ char l[32], L[32];
+ geoNum.s = IPS_OK;
+ fs_sexa (l, newLat, 3, 3600);
+ fs_sexa (L, newLong, 4, 3600);
+
+ if ( ( err = setSiteLongitude(360.0 - newLong) < 0) )
+ {
+ handleError(&geoNum, err, "Setting site coordinates");
+ return;
+ }
+
+ setSiteLatitude(newLat);
+ geoNum.np[0].value = newLat;
+ geoNum.np[1].value = newLong;
+ snprintf (msg, sizeof(msg), "Site location updated to Lat %.32s - Long %.32s", l, L);
+ } else
+ {
+ geoNum.s = IPS_IDLE;
+ strcpy(msg, "Lat or Long missing or invalid");
+ }
+ IDSetNumber (&geoNum, "%s", msg);
+ return;
+ }
+
+ if ( !strcmp (name, TrackingFreq.name) )
+ {
+
+ if (checkPower(&TrackingFreq))
+ return;
+
+ IDLog("Trying to set track freq of: %f\n", values[0]);
+
+ if ( ( err = setTrackFreq(values[0])) < 0)
+ {
+ handleError(&TrackingFreq, err, "Setting tracking frequency");
+ return;
+ }
+
+ TrackingFreq.s = IPS_OK;
+ TrackingFreq.np[0].value = values[0];
+ IDSetNumber(&TrackingFreq, "Tracking frequency set to %04.1f", values[0]);
+ if (trackingMode != LX200_TRACK_MANUAL)
+ {
+ trackingMode = LX200_TRACK_MANUAL;
+ TrackModeS[0].s = ISS_OFF;
+ TrackModeS[1].s = ISS_OFF;
+ TrackModeS[2].s = ISS_ON;
+ TrackModeSw.s = IPS_OK;
+ selectTrackingMode(trackingMode);
+ IDSetSwitch(&TrackModeSw, NULL);
+ }
+
+ return;
+ }
+
+ if (!strcmp(name, FocusTimerNP.name))
+ {
+ if (checkPower(&FocusTimerNP))
+ return;
+
+ // Don't update if busy
+ if (FocusTimerNP.s == IPS_BUSY)
+ return;
+
+ IUUpdateNumbers(&FocusTimerNP, values, names, n);
+
+ FocusTimerNP.s = IPS_OK;
+
+ IDSetNumber(&FocusTimerNP, NULL);
+ IDLog("Setting focus timer to %g\n", FocusTimerN[0].value);
+
+ return;
+
+ }
+
+ // Focus speed
+ if (!strcmp (name, FocusSpeedNP.name))
+ {
+ if (checkPower(&FocusSpeedNP))
+ return;
+
+ if (IUUpdateNumbers(&FocusSpeedNP, values, names, n) < 0)
+ return;
+
+ /* disable timer and motion */
+ if (FocusSpeedN[0].value == 0)
+ {
+ IUResetSwitches(&FocusMotionSw);
+ FocusMotionSw.s = IPS_IDLE;
+ FocusTimerNP.s = IPS_IDLE;
+ IDSetSwitch(&FocusMotionSw, NULL);
+ IDSetNumber(&FocusTimerNP, NULL);
+ }
+
+ setFocuserSpeedMode( ( (int) FocusSpeedN[0].value));
+ FocusSpeedNP.s = IPS_OK;
+ IDSetNumber(&FocusSpeedNP, NULL);
+ return;
+ }
+
+}
+
+void LX200Generic::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ int index;
+ int dd, mm, err;
+ char combinedDir[64];
+ ISwitch *swp;
+
+ // suppress warning
+ names = names;
+
+ //IDLog("in new Switch with Device= %s and Property= %s and #%d items\n", dev, name,n);
+ //IDLog("SolarSw name is %s\n", SolarSw.name);
+
+ //IDLog("The device name is %s\n", dev);
+ // ignore if not ours //
+ if (strcmp (thisDevice, dev))
+ return;
+
+ // FIRST Switch ALWAYS for power
+ if (!strcmp (name, PowerSP.name))
+ {
+ IUResetSwitches(&PowerSP);
+ IUUpdateSwitches(&PowerSP, states, names, n);
+ powerTelescope();
+ return;
+ }
+
+ // Coord set
+ if (!strcmp(name, OnCoordSetSw.name))
+ {
+ if (checkPower(&OnCoordSetSw))
+ return;
+
+ IUResetSwitches(&OnCoordSetSw);
+ IUUpdateSwitches(&OnCoordSetSw, states, names, n);
+ currentSet = getOnSwitch(&OnCoordSetSw);
+ OnCoordSetSw.s = IPS_OK;
+ IDSetSwitch(&OnCoordSetSw, NULL);
+ }
+
+ // Parking
+ if (!strcmp(name, ParkSP.name))
+ {
+ if (checkPower(&ParkSP))
+ return;
+
+ ParkSP.s = IPS_IDLE;
+
+
+ if ( (err = getSDTime(&STime[0].value)) < 0)
+ {
+ handleError(&ParkSP, err, "Get siderial time");
+ return;
+ }
+
+ if (AlignmentS[0].s == ISS_ON)
+ {
+ targetRA = STime[0].value;
+ targetDEC = 0;
+ setObjectRA(targetRA);
+ setObjectDEC(targetDEC);
+ }
+
+ else if (AlignmentS[1].s == ISS_ON)
+ {
+ targetRA = calculateRA(STime[0].value);
+ targetDEC = calculateDec(geo[0].value, STime[0].value);
+ setObjectRA(targetRA);
+ setObjectDEC(targetDEC);
+ IDLog("Parking the scope in AltAz (0,0) which corresponds to (RA,DEC) of (%g,%g)\n", targetRA, targetDEC);
+ IDLog("Current Sidereal time is: %g\n", STime[0].value);
+ IDSetNumber(&SDTime, NULL);
+ }
+ else
+ {
+ IDSetSwitch(&ParkSP, "You can only park the telescope in Polar or AltAz modes.");
+ return;
+ }
+
+ IDSetNumber(&SDTime, NULL);
+
+ currentSet = LX200_PARK;
+ handleCoordSet();
+ }
+
+ // Abort Slew
+ if (!strcmp (name, abortSlewSw.name))
+ {
+ if (checkPower(&abortSlewSw))
+ {
+ abortSlewSw.s = IPS_IDLE;
+ IDSetSwitch(&abortSlewSw, NULL);
+ return;
+ }
+
+ IUResetSwitches(&abortSlewSw);
+ abortSlew();
+
+ if (eqNum.s == IPS_BUSY)
+ {
+ abortSlewSw.s = IPS_OK;
+ eqNum.s = IPS_IDLE;
+ IDSetSwitch(&abortSlewSw, "Slew aborted.");
+ IDSetNumber(&eqNum, NULL);
+ }
+ else if (MovementSw.s == IPS_BUSY)
+ {
+
+ for (int i=0; i < 4; i++)
+ lastMove[i] = 0;
+
+ MovementSw.s = IPS_IDLE;
+ abortSlewSw.s = IPS_OK;
+ eqNum.s = IPS_IDLE;
+ IUResetSwitches(&MovementSw);
+ IUResetSwitches(&abortSlewSw);
+ IDSetSwitch(&abortSlewSw, "Slew aborted.");
+ IDSetSwitch(&MovementSw, NULL);
+ IDSetNumber(&eqNum, NULL);
+ }
+ else
+ {
+ IUResetSwitches(&MovementSw);
+ abortSlewSw.s = IPS_OK;
+ IDSetSwitch(&abortSlewSw, NULL);
+ }
+
+ return;
+ }
+
+ // Alignment
+ if (!strcmp (name, AlignmentSw.name))
+ {
+ if (checkPower(&AlignmentSw))
+ return;
+
+ IUResetSwitches(&AlignmentSw);
+ IUUpdateSwitches(&AlignmentSw, states, names, n);
+ index = getOnSwitch(&AlignmentSw);
+
+ if ( ( err = setAlignmentMode(index) < 0) )
+ {
+ handleError(&AlignmentSw, err, "Setting alignment");
+ return;
+ }
+
+ AlignmentSw.s = IPS_OK;
+ IDSetSwitch (&AlignmentSw, NULL);
+ return;
+
+ }
+
+ // Sites
+ if (!strcmp (name, SitesSw.name))
+ {
+ if (checkPower(&SitesSw))
+ return;
+
+ IUResetSwitches(&SitesSw);
+ IUUpdateSwitches(&SitesSw, states, names, n);
+ currentSiteNum = getOnSwitch(&SitesSw) + 1;
+
+ if ( ( err = selectSite(currentSiteNum) < 0) )
+ {
+ handleError(&SitesSw, err, "Selecting sites");
+ return;
+ }
+
+ if ( ( err = getSiteLatitude(&dd, &mm) < 0))
+ {
+ handleError(&SitesSw, err, "Selecting sites");
+ return;
+ }
+
+ if (dd > 0) geoNum.np[0].value = dd + mm / 60.0;
+ else geoNum.np[0].value = dd - mm / 60.0;
+
+ if ( ( err = getSiteLongitude(&dd, &mm) < 0))
+ {
+ handleError(&SitesSw, err, "Selecting sites");
+ return;
+ }
+
+ if (dd > 0) geoNum.np[1].value = 360.0 - (dd + mm / 60.0);
+ else geoNum.np[1].value = (dd - mm / 60.0) * -1.0;
+
+ getSiteName( SiteName.tp[0].text, currentSiteNum);
+
+ IDLog("Selecting site %d\n", currentSiteNum);
+
+ geoNum.s = SiteName.s = SitesSw.s = IPS_OK;
+
+ IDSetNumber (&geoNum, NULL);
+ IDSetText (&SiteName, NULL);
+ IDSetSwitch (&SitesSw, NULL);
+ return;
+ }
+
+ // Focus Motion
+ if (!strcmp (name, FocusMotionSw.name))
+ {
+ if (checkPower(&FocusMotionSw))
+ return;
+
+ IUResetSwitches(&FocusMotionSw);
+
+ // If speed is "halt"
+ if (FocusSpeedN[0].value == 0)
+ {
+ FocusMotionSw.s = IPS_IDLE;
+ IDSetSwitch(&FocusMotionSw, NULL);
+ return;
+ }
+
+ IUUpdateSwitches(&FocusMotionSw, states, names, n);
+ index = getOnSwitch(&FocusMotionSw);
+
+
+ if ( ( err = setFocuserMotion(index) < 0) )
+ {
+ handleError(&FocusMotionSw, err, "Setting focuser speed");
+ return;
+ }
+
+
+ FocusMotionSw.s = IPS_BUSY;
+
+ // with a timer
+ if (FocusTimerN[0].value > 0)
+ FocusTimerNP.s = IPS_BUSY;
+
+ IDSetSwitch(&FocusMotionSw, NULL);
+ return;
+ }
+
+ // Slew mode
+ if (!strcmp (name, SlewModeSw.name))
+ {
+ if (checkPower(&SlewModeSw))
+ return;
+
+ IUResetSwitches(&SlewModeSw);
+ IUUpdateSwitches(&SlewModeSw, states, names, n);
+ index = getOnSwitch(&SlewModeSw);
+
+ if ( ( err = setSlewMode(index) < 0) )
+ {
+ handleError(&SlewModeSw, err, "Setting slew mode");
+ return;
+ }
+
+ SlewModeSw.s = IPS_OK;
+ IDSetSwitch(&SlewModeSw, NULL);
+ return;
+ }
+
+ // Movement
+ if (!strcmp (name, MovementSw.name))
+ {
+ if (checkPower(&MovementSw))
+ return;
+
+ index = -1;
+ IUUpdateSwitches(&MovementSw, states, names, n);
+ swp = IUFindSwitch(&MovementSw, names[0]);
+
+ if (!swp)
+ {
+ abortSlew();
+ IUResetSwitches(&MovementSw);
+ MovementSw.s = IPS_IDLE;
+ IDSetSwitch(&MovementSw, NULL);
+ }
+
+ if (swp == &MovementS[0]) index = 0;
+ else if (swp == &MovementS[1]) index = 1;
+ else if (swp == &MovementS[2]) index = 2;
+ else index = 3;
+
+ lastMove[index] = lastMove[index] == 0 ? 1 : 0;
+ if (lastMove[index] == 0)
+ MovementS[index].s = ISS_OFF;
+
+ // North/South movement is illegal
+ if (lastMove[LX200_NORTH] && lastMove[LX200_SOUTH])
+ {
+ abortSlew();
+ for (int i=0; i < 4; i++)
+ lastMove[i] = 0;
+
+ IUResetSwitches(&MovementSw);
+ MovementSw.s = IPS_IDLE;
+ IDSetSwitch(&MovementSw, "Slew aborted.");
+ return;
+ }
+
+ // East/West movement is illegal
+ if (lastMove[LX200_EAST] && lastMove[LX200_WEST])
+ {
+ abortSlew();
+ for (int i=0; i < 4; i++)
+ lastMove[i] = 0;
+
+ IUResetSwitches(&MovementSw);
+ MovementSw.s = IPS_IDLE;
+ IDSetSwitch(&MovementSw, "Slew aborted.");
+ return;
+ }
+
+ IDLog("We have switch %d \n ", index);
+ IDLog("NORTH: %d -- WEST: %d -- EAST: %d -- SOUTH %d\n", lastMove[0], lastMove[1], lastMove[2], lastMove[3]);
+
+ if (lastMove[index] == 1)
+ {
+ IDLog("issuing a move command\n");
+ if ( ( err = MoveTo(index) < 0) )
+ {
+ handleError(&MovementSw, err, "Setting motion direction");
+ return;
+ }
+ }
+ else
+ HaltMovement(index);
+
+ if (!lastMove[0] && !lastMove[1] && !lastMove[2] && !lastMove[3])
+ MovementSw.s = IPS_IDLE;
+
+ if (lastMove[index] == 0)
+ IDSetSwitch(&MovementSw, "Moving toward %s aborted.", Direction[index]);
+ else
+ {
+ MovementSw.s = IPS_BUSY;
+ if (lastMove[LX200_NORTH] && lastMove[LX200_WEST])
+ strcpy(combinedDir, "North West");
+ else if (lastMove[LX200_NORTH] && lastMove[LX200_EAST])
+ strcpy(combinedDir, "North East");
+ else if (lastMove[LX200_SOUTH] && lastMove[LX200_WEST])
+ strcpy(combinedDir, "South West");
+ else if (lastMove[LX200_SOUTH] && lastMove[LX200_EAST])
+ strcpy(combinedDir, "South East");
+ else
+ strcpy(combinedDir, Direction[index]);
+
+ IDSetSwitch(&MovementSw, "Moving %s...", combinedDir);
+ }
+ return;
+ }
+
+ // Tracking mode
+ if (!strcmp (name, TrackModeSw.name))
+ {
+ if (checkPower(&TrackModeSw))
+ return;
+
+ IUResetSwitches(&TrackModeSw);
+ IUUpdateSwitches(&TrackModeSw, states, names, n);
+ trackingMode = getOnSwitch(&TrackModeSw);
+
+ if ( ( err = selectTrackingMode(trackingMode) < 0) )
+ {
+ handleError(&TrackModeSw, err, "Setting tracking mode.");
+ return;
+ }
+
+ getTrackFreq(&TrackFreq[0].value);
+ TrackModeSw.s = IPS_OK;
+ IDSetNumber(&TrackingFreq, NULL);
+ IDSetSwitch(&TrackModeSw, NULL);
+ return;
+ }
+
+}
+
+void LX200Generic::handleError(ISwitchVectorProperty *svp, int err, const char *msg)
+{
+
+ svp->s = IPS_ALERT;
+
+ /* First check to see if the telescope is connected */
+ if (testTelescope())
+ {
+ /* The telescope is off locally */
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_BUSY;
+ IDSetSwitch(&PowerSP, "Telescope is not responding to commands, will retry in 10 seconds.");
+
+ IDSetSwitch(svp, NULL);
+ IEAddTimer(10000, retryConnection, NULL);
+ return;
+ }
+
+ /* If the error is a time out, then the device doesn't support this property or busy*/
+ if (err == -2)
+ {
+ svp->s = IPS_ALERT;
+ IDSetSwitch(svp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
+ }
+ else
+ /* Changing property failed, user should retry. */
+ IDSetSwitch( svp , "%s failed.", msg);
+
+ fault = true;
+}
+
+void LX200Generic::handleError(INumberVectorProperty *nvp, int err, const char *msg)
+{
+
+ nvp->s = IPS_ALERT;
+
+ /* First check to see if the telescope is connected */
+ if (testTelescope())
+ {
+ /* The telescope is off locally */
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_BUSY;
+ IDSetSwitch(&PowerSP, "Telescope is not responding to commands, will retry in 10 seconds.");
+
+ IDSetNumber(nvp, NULL);
+ IEAddTimer(10000, retryConnection, NULL);
+ return;
+ }
+
+ /* If the error is a time out, then the device doesn't support this property */
+ if (err == -2)
+ {
+ nvp->s = IPS_ALERT;
+ IDSetNumber(nvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
+ }
+ else
+ /* Changing property failed, user should retry. */
+ IDSetNumber( nvp , "%s failed.", msg);
+
+ fault = true;
+}
+
+void LX200Generic::handleError(ITextVectorProperty *tvp, int err, const char *msg)
+{
+
+ tvp->s = IPS_ALERT;
+
+ /* First check to see if the telescope is connected */
+ if (testTelescope())
+ {
+ /* The telescope is off locally */
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_BUSY;
+ IDSetSwitch(&PowerSP, "Telescope is not responding to commands, will retry in 10 seconds.");
+
+ IDSetText(tvp, NULL);
+ IEAddTimer(10000, retryConnection, NULL);
+ return;
+ }
+
+ /* If the error is a time out, then the device doesn't support this property */
+ if (err == -2)
+ {
+ tvp->s = IPS_ALERT;
+ IDSetText(tvp, "Device timed out. Current device may be busy or does not support %s. Will retry again.", msg);
+ }
+
+ else
+ /* Changing property failed, user should retry. */
+ IDSetText( tvp , "%s failed.", msg);
+
+ fault = true;
+}
+
+ void LX200Generic::correctFault()
+ {
+
+ fault = false;
+ IDMessage(thisDevice, "Telescope is online.");
+
+ }
+
+bool LX200Generic::isTelescopeOn(void)
+{
+ if (simulation) return true;
+
+ return (PowerSP.sp[0].s == ISS_ON);
+}
+
+static void retryConnection(void * p)
+{
+ p=p;
+
+ if (testTelescope())
+ {
+ PowerSP.s = IPS_IDLE;
+ IDSetSwitch(&PowerSP, "The connection to the telescope is lost.");
+ return;
+ }
+
+ PowerS[0].s = ISS_ON;
+ PowerS[1].s = ISS_OFF;
+ PowerSP.s = IPS_OK;
+
+ IDSetSwitch(&PowerSP, "The connection to the telescope has been resumed.");
+
+}
+
+void LX200Generic::ISPoll()
+{
+ double dx, dy;
+ /*static int okCounter = 3;*/
+ int err=0;
+
+ if (!isTelescopeOn())
+ return;
+
+ switch (eqNum.s)
+ {
+ case IPS_IDLE:
+ getLX200RA(&currentRA);
+ getLX200DEC(&currentDEC);
+
+ if ( fabs (currentRA - lastRA) > 0.01 || fabs (currentDEC - lastDEC) > 0.01)
+ {
+ eqNum.np[0].value = lastRA = currentRA;
+ eqNum.np[1].value = lastDEC = currentDEC;
+ IDSetNumber (&eqNum, NULL);
+ }
+ break;
+
+ case IPS_BUSY:
+ getLX200RA(&currentRA);
+ getLX200DEC(&currentDEC);
+ dx = targetRA - currentRA;
+ dy = targetDEC - currentDEC;
+
+ IDLog("targetRA is %g, currentRA is %g\n", targetRA, currentRA);
+ IDLog("targetDEC is %g, currentDEC is %g\n*************************\n", targetDEC, currentDEC);
+
+ eqNum.np[0].value = currentRA;
+ eqNum.np[1].value = currentDEC;
+
+ // Wait until acknowledged or within threshold
+ if (fabs(dx) <= RA_THRESHOLD && fabs(dy) <= DEC_THRESHOLD)
+ {
+ /* Don't set current to target. This might leave residual cumulative error
+ currentRA = targetRA;
+ currentDEC = targetDEC;
+ */
+
+ eqNum.np[0].value = lastRA = currentRA;
+ eqNum.np[1].value = lastDEC = currentDEC;
+ IUResetSwitches(&OnCoordSetSw);
+ OnCoordSetSw.s = IPS_OK;
+ eqNum.s = IPS_OK;
+ IDSetNumber (&eqNum, NULL);
+
+ switch (currentSet)
+ {
+ case LX200_SLEW:
+ OnCoordSetSw.sp[0].s = ISS_ON;
+ IDSetSwitch (&OnCoordSetSw, "Slew is complete.");
+ break;
+
+ case LX200_TRACK:
+ OnCoordSetSw.sp[1].s = ISS_ON;
+ IDSetSwitch (&OnCoordSetSw, "Slew is complete. Tracking...");
+ break;
+
+ case LX200_SYNC:
+ break;
+
+ case LX200_PARK:
+ if (setSlewMode(LX200_SLEW_GUIDE) < 0)
+ {
+ handleError(&eqNum, err, "Setting slew mode");
+ return;
+ }
+
+ IUResetSwitches(&SlewModeSw);
+ SlewModeS[LX200_SLEW_GUIDE].s = ISS_ON;
+ IDSetSwitch(&SlewModeSw, NULL);
+
+ MoveTo(LX200_EAST);
+ IUResetSwitches(&MovementSw);
+ MovementS[LX200_EAST].s = ISS_ON;
+ MovementSw.s = IPS_BUSY;
+ for (int i=0; i < 4; i++)
+ lastMove[i] = 0;
+ lastMove[LX200_EAST] = 1;
+ IDSetSwitch(&MovementSw, NULL);
+
+ ParkSP.s = IPS_OK;
+ IDSetSwitch (&ParkSP, "Park is complete. Turn off the telescope now.");
+ break;
+ }
+
+ } else
+ {
+ eqNum.np[0].value = currentRA;
+ eqNum.np[1].value = currentDEC;
+ IDSetNumber (&eqNum, NULL);
+ }
+ break;
+
+ case IPS_OK:
+
+ /*if (--okCounter >= 0)
+ break;
+
+ // Activate again in 3 seconds
+ okCounter = 3;*/
+
+ if ( (err = getLX200RA(&currentRA)) < 0 || (err = getLX200DEC(&currentDEC)) < 0)
+ {
+ handleError(&eqNum, err, "Getting RA/DEC");
+ return;
+ }
+
+ if (fault)
+ correctFault();
+
+ if ( (currentRA != lastRA) || (currentDEC != lastDEC))
+ {
+ eqNum.np[0].value = lastRA = currentRA;
+ eqNum.np[1].value = lastDEC = currentDEC;
+ IDSetNumber (&eqNum, NULL);
+ }
+ break;
+
+
+ case IPS_ALERT:
+ break;
+ }
+
+ switch (MovementSw.s)
+ {
+ case IPS_IDLE:
+ break;
+ case IPS_BUSY:
+ getLX200RA(&currentRA);
+ getLX200DEC(&currentDEC);
+ /*apparentCoord( JD, (double) J2000, &currentRA, &currentDEC);*/
+ eqNum.np[0].value = currentRA;
+ eqNum.np[1].value = currentDEC;
+
+ IDSetNumber (&eqNum, NULL);
+ break;
+ case IPS_OK:
+ break;
+ case IPS_ALERT:
+ break;
+ }
+
+ switch (FocusTimerNP.s)
+ {
+ case IPS_IDLE:
+ break;
+
+ case IPS_BUSY:
+ FocusTimerN[0].value--;
+
+ if (FocusTimerN[0].value == 0)
+ {
+
+ if ( ( err = setFocuserSpeedMode(0) < 0) )
+ {
+ handleError(&FocusSpeedNP, err, "setting focuser speed mode");
+ IDLog("Error setting focuser speed mode\n");
+ return;
+ }
+
+
+ FocusMotionSw.s = IPS_IDLE;
+ FocusTimerNP.s = IPS_OK;
+ FocusSpeedNP.s = IPS_OK;
+
+ IUResetSwitches(&FocusMotionSw);
+ FocusSpeedN[0].value = 0;
+
+ IDSetNumber(&FocusSpeedNP, NULL);
+ IDSetSwitch(&FocusMotionSw, NULL);
+ }
+
+ IDSetNumber(&FocusTimerNP, NULL);
+ break;
+
+ case IPS_OK:
+ break;
+
+ case IPS_ALERT:
+ break;
+ }
+
+
+}
+
+void LX200Generic::getBasicData()
+{
+
+ int err;
+ struct tm *timep;
+ time_t ut;
+ time (&ut);
+ timep = gmtime (&ut);
+ strftime (Time.tp[0].text, sizeof(Time.tp[0].text), "%Y-%m-%dT%H:%M:%S", timep);
+
+ IDLog("PC UTC time is %s\n", Time.tp[0].text);
+
+ getAlignment();
+
+ checkLX200Format();
+
+ if ( (err = getTimeFormat(&timeFormat)) < 0)
+ IDMessage(thisDevice, "Failed to retrieve time format from device.");
+ else
+ {
+ timeFormat = (timeFormat == 24) ? LX200_24 : LX200_AM;
+ // We always do 24 hours
+ if (timeFormat != LX200_24)
+ toggleTimeFormat();
+ }
+
+ getLX200RA(&targetRA);
+ getLX200DEC(&targetDEC);
+
+ eqNum.np[0].value = targetRA;
+ eqNum.np[1].value = targetDEC;
+
+ IDSetNumber (&eqNum, NULL);
+
+ SiteNameT[0].text = new char[64];
+
+ if ( (err = getSiteName(SiteNameT[0].text, currentSiteNum)) < 0)
+ IDMessage(thisDevice, "Failed to get site name from device");
+ else
+ IDSetText (&SiteName, NULL);
+
+ if ( (err = getTrackFreq(&TrackFreq[0].value)) < 0)
+ IDMessage(thisDevice, "Failed to get tracking frequency from device.");
+ else
+ IDSetNumber (&TrackingFreq, NULL);
+
+
+ updateLocation();
+ updateTime();
+
+}
+
+int LX200Generic::handleCoordSet()
+{
+
+ int err;
+ char syncString[256];
+ char RAStr[32], DecStr[32];
+ double dx, dy;
+
+ IDLog("In Handle Coord Set()\n");
+
+ switch (currentSet)
+ {
+
+ // Slew
+ case LX200_SLEW:
+ lastSet = LX200_SLEW;
+ if (eqNum.s == IPS_BUSY)
+ {
+ IDLog("Aboring Slew\n");
+ abortSlew();
+
+ // sleep for 100 mseconds
+ usleep(100000);
+ }
+
+ if ((err = Slew()))
+ {
+ slewError(err);
+ return (-1);
+ }
+
+ eqNum.s = IPS_BUSY;
+ fs_sexa(RAStr, targetRA, 2, 3600);
+ fs_sexa(DecStr, targetDEC, 2, 3600);
+ IDSetNumber(&eqNum, "Slewing to JNow RA %s - DEC %s", RAStr, DecStr);
+ IDLog("Slewing to JNow RA %s - DEC %s\n", RAStr, DecStr);
+ break;
+
+ // Track
+ case LX200_TRACK:
+ IDLog("We're in LX200_TRACK\n");
+ if (eqNum.s == IPS_BUSY)
+ {
+ IDLog("Aboring Slew\n");
+ abortSlew();
+
+ // sleep for 200 mseconds
+ usleep(200000);
+ }
+
+ dx = fabs ( targetRA - currentRA );
+ dy = fabs (targetDEC - currentDEC);
+
+
+ if (dx >= TRACKING_THRESHOLD || dy >= TRACKING_THRESHOLD)
+ {
+ IDLog("Exceeded Tracking threshold, will attempt to slew to the new target.\n");
+ IDLog("targetRA is %g, currentRA is %g\n", targetRA, currentRA);
+ IDLog("targetDEC is %g, currentDEC is %g\n*************************\n", targetDEC, currentDEC);
+
+ if ((err = Slew()))
+ {
+ slewError(err);
+ return (-1);
+ }
+
+ fs_sexa(RAStr, targetRA, 2, 3600);
+ fs_sexa(DecStr, targetDEC, 2, 3600);
+ eqNum.s = IPS_BUSY;
+ IDSetNumber(&eqNum, "Slewing to JNow RA %s - DEC %s", RAStr, DecStr);
+ IDLog("Slewing to JNow RA %s - DEC %s\n", RAStr, DecStr);
+ }
+ else
+ {
+ IDLog("Tracking called, but tracking threshold not reached yet.\n");
+ eqNum.s = IPS_OK;
+ eqNum.np[0].value = currentRA;
+ eqNum.np[1].value = currentDEC;
+
+ if (lastSet != LX200_TRACK)
+ IDSetNumber(&eqNum, "Tracking...");
+ else
+ IDSetNumber(&eqNum, NULL);
+ }
+ lastSet = LX200_TRACK;
+ break;
+
+ // Sync
+ case LX200_SYNC:
+ lastSet = LX200_SYNC;
+ eqNum.s = IPS_IDLE;
+
+ if ( ( err = Sync(syncString) < 0) )
+ {
+ IDSetNumber( &eqNum , "Synchronization failed.");
+ return (-1);
+ }
+
+ eqNum.s = IPS_OK;
+ IDLog("Synchronization successful %s\n", syncString);
+ IDSetNumber(&eqNum, "Synchronization successful.");
+ break;
+
+ // PARK
+ // Set RA to LST and DEC to 0 degrees, slew, then change to 'guide' slew after slew is complete.
+ case LX200_PARK:
+ if (eqNum.s == IPS_BUSY)
+ {
+ abortSlew();
+
+ // sleep for 200 mseconds
+ usleep(200000);
+ }
+
+ if ((err = Slew()))
+ {
+ slewError(err);
+ return (-1);
+ }
+
+ ParkSP.s = IPS_BUSY;
+ eqNum.s = IPS_BUSY;
+ IDSetNumber(&eqNum, NULL);
+ IDSetSwitch(&ParkSP, "The telescope is slewing to park position. Turn off the telescope after park is complete.");
+
+ break;
+
+ }
+
+ return (0);
+
+}
+
+int LX200Generic::getOnSwitch(ISwitchVectorProperty *sp)
+{
+ for (int i=0; i < sp->nsp ; i++)
+ if (sp->sp[i].s == ISS_ON)
+ return i;
+
+ return -1;
+}
+
+
+int LX200Generic::checkPower(ISwitchVectorProperty *sp)
+{
+ if (simulation) return 0;
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(sp->label, ""))
+ IDMessage (thisDevice, "Cannot change property %s while the telescope is offline.", sp->name);
+ else
+ IDMessage (thisDevice, "Cannot change property %s while the telescope is offline.", sp->label);
+
+ sp->s = IPS_IDLE;
+ IDSetSwitch(sp, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int LX200Generic::checkPower(INumberVectorProperty *np)
+{
+ if (simulation) return 0;
+
+ if (PowerSP.s != IPS_OK)
+ {
+
+ if (!strcmp(np->label, ""))
+ IDMessage (thisDevice, "Cannot change property %s while the telescope is offline.", np->name);
+ else
+ IDMessage (thisDevice, "Cannot change property %s while the telescope is offline.", np->label);
+
+ np->s = IPS_IDLE;
+ IDSetNumber(np, NULL);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+int LX200Generic::checkPower(ITextVectorProperty *tp)
+{
+
+ if (simulation) return 0;
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(tp->label, ""))
+ IDMessage (thisDevice, "Cannot change property %s while the telescope is offline.", tp->name);
+ else
+ IDMessage (thisDevice, "Cannot change property %s while the telescope is offline.", tp->label);
+
+ tp->s = IPS_IDLE;
+ IDSetText(tp, NULL);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+void LX200Generic::powerTelescope()
+{
+ switch (PowerSP.sp[0].s)
+ {
+ case ISS_ON:
+
+ if (simulation)
+ {
+ PowerSP.s = IPS_OK;
+ IDSetSwitch (&PowerSP, "Simulated telescope is online.");
+ updateTime();
+ return;
+ }
+
+ if (Connect(Port.tp[0].text))
+ {
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch (&PowerSP, "Error connecting to port %s\n", Port.tp[0].text);
+ return;
+ }
+ if (testTelescope())
+ {
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch (&PowerSP, "Error connecting to Telescope. Telescope is offline.");
+ return;
+ }
+
+ IDLog("telescope test successfful\n");
+ PowerSP.s = IPS_OK;
+ IDSetSwitch (&PowerSP, "Telescope is online. Retrieving basic data...");
+ getBasicData();
+ break;
+
+ case ISS_OFF:
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_IDLE;
+ IDSetSwitch (&PowerSP, "Telescope is offline.");
+ IDLog("Telescope is offline.");
+ Disconnect();
+ break;
+
+ }
+
+}
+
+void LX200Generic::slewError(int slewCode)
+{
+ OnCoordSetSw.s = IPS_IDLE;
+ ParkSP.s = IPS_IDLE;
+ IDSetSwitch(&ParkSP, NULL);
+
+ if (slewCode == 1)
+ IDSetSwitch (&OnCoordSetSw, "Object below horizon.");
+ else if (slewCode == 2)
+ IDSetSwitch (&OnCoordSetSw, "Object below the minimum elevation limit.");
+ else
+ IDSetSwitch (&OnCoordSetSw, "Slew failed.");
+
+
+}
+
+void LX200Generic::getAlignment()
+{
+
+ if (PowerSP.s != IPS_OK)
+ return;
+
+ signed char align = ACK();
+ if (align < 0)
+ {
+ IDSetSwitch (&AlignmentSw, "Failed to get telescope alignment.");
+ return;
+ }
+
+ AlignmentS[0].s = ISS_OFF;
+ AlignmentS[1].s = ISS_OFF;
+ AlignmentS[2].s = ISS_OFF;
+
+ switch (align)
+ {
+ case 'P': AlignmentS[0].s = ISS_ON;
+ break;
+ case 'A': AlignmentS[1].s = ISS_ON;
+ break;
+ case 'L': AlignmentS[2].s = ISS_ON;
+ break;
+ }
+
+ AlignmentSw.s = IPS_OK;
+ IDSetSwitch (&AlignmentSw, NULL);
+ IDLog("ACK success %c\n", align);
+}
+
+void LX200Generic::enableSimulation(bool enable)
+{
+ simulation = enable;
+
+ if (simulation)
+ IDLog("Warning: Simulation is activated.\n");
+ else
+ IDLog("Simulation is disabled.\n");
+}
+
+void LX200Generic::updateTime()
+{
+
+ char cdate[32];
+ double ctime;
+ int h, m, s;
+ int day, month, year, result;
+ int UTC_h, UTC_month, UTC_year, UTC_day, daysInFeb;
+ bool leapYear;
+
+ tzset();
+
+ UTCOffset = timezoneOffset();
+ IDLog("Daylight: %s - TimeZone: %g\n", daylight ? "Yes" : "No", UTCOffset);
+
+
+ if (simulation)
+ {
+ sprintf(UTC[0].text, "%d-%02d-%02dT%02d:%02d:%02d", 1979, 6, 25, 3, 30, 30);
+ IDLog("Telescope ISO date and time: %s\n", UTC[0].text);
+ IDSetText(&Time, NULL);
+ return;
+ }
+
+ getLocalTime24(&ctime);
+ getSexComponents(ctime, &h, &m, &s);
+
+ UTC_h = h;
+
+ if ( (result = getSDTime(&STime[0].value)) < 0)
+ IDMessage(thisDevice, "Failed to retrieve siderial time from device.");
+
+ getCalenderDate(cdate);
+
+ result = sscanf(cdate, "%d/%d/%d", &year, &month, &day);
+ if (result != 3) return;
+
+ if (year % 4 == 0)
+ {
+ if (year % 100 == 0)
+ {
+ if (year % 400 == 0)
+ leapYear = true;
+ else
+ leapYear = false;
+ }
+ else
+ leapYear = true;
+ }
+ else
+ leapYear = false;
+
+ daysInFeb = leapYear ? 29 : 28;
+
+ UTC_year = year;
+ UTC_month = month;
+ UTC_day = day;
+
+ IDLog("day: %d - month %d - year: %d\n", day, month, year);
+
+ // we'll have to convert telescope time to UTC manually starting from hour up
+ // seems like a stupid way to do it.. oh well
+ UTC_h = (int) UTCOffset + h;
+ if (UTC_h < 0)
+ {
+ UTC_h += 24;
+ UTC_day--;
+ }
+ else if (UTC_h > 24)
+ {
+ UTC_h -= 24;
+ UTC_day++;
+ }
+
+ switch (UTC_month)
+ {
+ case 1:
+ case 8:
+ if (UTC_day < 1)
+ {
+ UTC_day = 31;
+ UTC_month--;
+ }
+ else if (UTC_day > 31)
+ {
+ UTC_day = 1;
+ UTC_month++;
+ }
+ break;
+
+ case 2:
+ if (UTC_day < 1)
+ {
+ UTC_day = 31;
+ UTC_month--;
+ }
+ else if (UTC_day > daysInFeb)
+ {
+ UTC_day = 1;
+ UTC_month++;
+ }
+ break;
+
+ case 3:
+ if (UTC_day < 1)
+ {
+ UTC_day = daysInFeb;
+ UTC_month--;
+ }
+ else if (UTC_day > 31)
+ {
+ UTC_day = 1;
+ UTC_month++;
+ }
+ break;
+
+ case 4:
+ case 6:
+ case 9:
+ case 11:
+ if (UTC_day < 1)
+ {
+ UTC_day = 31;
+ UTC_month--;
+ }
+ else if (UTC_day > 30)
+ {
+ UTC_day = 1;
+ UTC_month++;
+ }
+ break;
+
+ case 5:
+ case 7:
+ case 10:
+ case 12:
+ if (UTC_day < 1)
+ {
+ UTC_day = 30;
+ UTC_month--;
+ }
+ else if (UTC_day > 31)
+ {
+ UTC_day = 1;
+ UTC_month++;
+ }
+ break;
+
+ }
+
+ if (UTC_month < 1)
+ {
+ UTC_month = 12;
+ UTC_year--;
+ }
+ else if (UTC_month > 12)
+ {
+ UTC_month = 1;
+ UTC_year++;
+ }
+
+ /* Format it into ISO 8601 */
+ sprintf(UTC[0].text, "%d-%02d-%02dT%02d:%02d:%02d", UTC_year, UTC_month, UTC_day, UTC_h, m, s);
+
+ IDLog("Local telescope time: %02d:%02d:%02d\n", h, m , s);
+ IDLog("Telescope SD Time is: %g\n", STime[0].value);
+ IDLog("UTC date and time: %s\n", UTC[0].text);
+
+
+ // Let's send everything to the client
+ IDSetText(&Time, NULL);
+ IDSetNumber(&SDTime, NULL);
+
+}
+
+void LX200Generic::updateLocation()
+{
+
+ int dd = 0, mm = 0, err = 0;
+
+ if ( (err = getSiteLatitude(&dd, &mm)) < 0)
+ IDMessage(thisDevice, "Failed to get site latitude from device.");
+ else
+ {
+ if (dd > 0)
+ geoNum.np[0].value = dd + mm/60.0;
+ else
+ geoNum.np[0].value = dd - mm/60.0;
+
+ IDLog("Autostar Latitude: %d:%d\n", dd, mm);
+ IDLog("INDI Latitude: %g\n", geoNum.np[0].value);
+ }
+
+ if ( (err = getSiteLongitude(&dd, &mm)) < 0)
+ IDMessage(thisDevice, "Failed to get site longitude from device.");
+ else
+ {
+ if (dd > 0) geoNum.np[1].value = 360.0 - (dd + mm/60.0);
+ else geoNum.np[1].value = (dd - mm/60.0) * -1.0;
+
+ IDLog("Autostar Longitude: %d:%d\n", dd, mm);
+ IDLog("INDI Longitude: %g\n", geoNum.np[1].value);
+ }
+
+ IDSetNumber (&geoNum, NULL);
+
+}
+
+
diff --git a/kstars/kstars/indi/lx200generic.h b/kstars/kstars/indi/lx200generic.h
new file mode 100644
index 00000000..569b500b
--- /dev/null
+++ b/kstars/kstars/indi/lx200generic.h
@@ -0,0 +1,91 @@
+/*
+ LX200 Generic
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef LX200GENERIC_H
+#define LX200GENERIC_H
+
+#include "indidevapi.h"
+#include "indicom.h"
+
+#define POLLMS 1000 /* poll period, ms */
+#define mydev "LX200 Generic" /* The device name */
+
+class LX200Generic
+{
+ public:
+ LX200Generic();
+ virtual ~LX200Generic() {}
+
+ virtual void ISGetProperties (const char *dev);
+ virtual void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+ virtual void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ virtual void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+ virtual void ISPoll ();
+ virtual void getBasicData();
+
+ int checkPower(INumberVectorProperty *np);
+ int checkPower(ISwitchVectorProperty *sp);
+ int checkPower(ITextVectorProperty *tp);
+ void handleError(ISwitchVectorProperty *svp, int err, const char *msg);
+ void handleError(INumberVectorProperty *nvp, int err, const char *msg);
+ void handleError(ITextVectorProperty *tvp, int err, const char *msg);
+ bool isTelescopeOn(void);
+ void powerTelescope();
+ void slewError(int slewCode);
+ void getAlignment();
+ int handleCoordSet();
+ int getOnSwitch(ISwitchVectorProperty *sp);
+ void setCurrentDeviceName(const char * devName);
+ void correctFault();
+ void enableSimulation(bool enable);
+ void updateTime();
+ void updateLocation();
+
+
+ protected:
+ int timeFormat;
+ int currentSiteNum;
+ int trackingMode;
+
+ double JD;
+ double currentRA;
+ double currentDEC;
+ double targetRA;
+ double targetDEC;
+ double lastRA;
+ double lastDEC;
+ double UTCOffset;
+ bool fault;
+ bool simulation;
+
+ struct tm *localTM;
+
+ char thisDevice[64];
+
+ int currentSet;
+ int lastSet;
+ int lastMove[4];
+
+};
+
+void changeLX200GenericDeviceName(const char * newName);
+void changeAllDeviceNames(const char *newName);
+
+#endif
diff --git a/kstars/kstars/indi/lx200gps.cpp b/kstars/kstars/indi/lx200gps.cpp
new file mode 100644
index 00000000..451a7269
--- /dev/null
+++ b/kstars/kstars/indi/lx200gps.cpp
@@ -0,0 +1,340 @@
+/*
+ LX200 GPS
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "lx200gps.h"
+#include "lx200driver.h"
+
+#define GPSGroup "Extended GPS Features"
+
+extern LX200Generic *telescope;
+extern int MaxReticleFlashRate;
+
+static ISwitch GPSPowerS[] = {{ "On", "", ISS_OFF, 0, 0}, {"Off", "", ISS_ON, 0, 0}};
+static ISwitch GPSStatusS[] = {{ "Sleep", "", ISS_OFF, 0, 0}, {"Wake up", "", ISS_OFF, 0 ,0}, {"Restart", "", ISS_OFF, 0, 0}};
+static ISwitch GPSUpdateS[] = { {"Update", "", ISS_OFF, 0, 0}};
+static ISwitch AltDecPecS[] = {{ "Enable", "", ISS_OFF, 0 ,0}, {"Disable", "", ISS_OFF, 0 ,0}};
+static ISwitch AzRaPecS[] = {{ "Enable", "", ISS_OFF, 0, 0}, {"Disable", "", ISS_OFF, 0 ,0}};
+static ISwitch SelenSyncS[] = {{ "Sync", "", ISS_OFF, 0, 0}};
+static ISwitch AltDecBackSlashS[] = {{ "Activate", "", ISS_OFF, 0, 0}};
+static ISwitch AzRaBackSlashS[] = {{ "Activate", "", ISS_OFF, 0, 0}};
+static ISwitch OTAUpdateS[] = {{ "Update", "", ISS_OFF, 0, 0}};
+
+static ISwitchVectorProperty GPSPowerSw = { mydev, "GPS Power", "", GPSGroup, IP_RW, ISR_1OFMANY, 0 , IPS_IDLE, GPSPowerS, NARRAY(GPSPowerS), "", 0};
+static ISwitchVectorProperty GPSStatusSw = { mydev, "GPS Status", "", GPSGroup, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, GPSStatusS, NARRAY(GPSStatusS), "", 0};
+static ISwitchVectorProperty GPSUpdateSw = { mydev, "GPS System", "", GPSGroup, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, GPSUpdateS, NARRAY(GPSUpdateS), "", 0};
+static ISwitchVectorProperty AltDecPecSw = { mydev, "Alt/Dec PEC", "", GPSGroup, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, AltDecPecS, NARRAY(AltDecPecS), "", 0};
+static ISwitchVectorProperty AzRaPecSw = { mydev, "Az/Ra PEC", "", GPSGroup, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, AzRaPecS, NARRAY(AzRaPecS), "", 0};
+static ISwitchVectorProperty SelenSyncSw = { mydev, "Selenographic Sync", "", GPSGroup, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, SelenSyncS, NARRAY(SelenSyncS), "", 0};
+static ISwitchVectorProperty AltDecBackSlashSw = { mydev, "Alt/Dec Anti-backslash", "", GPSGroup, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, AltDecBackSlashS, NARRAY(AltDecBackSlashS), "", 0};
+static ISwitchVectorProperty AzRaBackSlashSw = { mydev, "Az/Ra Anti-backslash", "", GPSGroup, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, AzRaBackSlashS, NARRAY(AzRaBackSlashS), "", 0};
+static ISwitchVectorProperty OTAUpdateSw = { mydev, "OTA Update", "", GPSGroup, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, OTAUpdateS, NARRAY(OTAUpdateS), "", 0};
+
+static INumber Temp[] = { {"Temp.", "", "%g", -200., 500., 0., 0., 0, 0, 0 } };
+static INumberVectorProperty OTATemp = { mydev, "OTA Temperature (C)", "", GPSGroup, IP_RO, 0, IPS_IDLE, Temp, NARRAY(Temp), "", 0};
+
+void updateTemp(void * /*p*/);
+
+void changeLX200GPSDeviceName(const char *newName)
+{
+ strcpy(GPSPowerSw.device, newName);
+ strcpy(GPSStatusSw.device, newName );
+ strcpy(GPSUpdateSw.device, newName );
+ strcpy(AltDecPecSw.device, newName );
+ strcpy(AzRaPecSw.device,newName );
+ strcpy(SelenSyncSw.device, newName );
+ strcpy(AltDecBackSlashSw.device, newName );
+ strcpy(AzRaBackSlashSw.device, newName );
+ strcpy(OTATemp.device, newName );
+ strcpy(OTAUpdateSw.device, newName);
+
+}
+
+LX200GPS::LX200GPS() : LX200_16()
+{
+ IEAddTimer(900000, updateTemp, NULL);
+
+}
+
+void LX200GPS::ISGetProperties (const char *dev)
+{
+
+if (dev && strcmp (thisDevice, dev))
+ return;
+
+// process parent first
+ LX200_16::ISGetProperties(dev);
+
+IDDefSwitch (&GPSPowerSw, NULL);
+IDDefSwitch (&GPSStatusSw, NULL);
+IDDefSwitch (&GPSUpdateSw, NULL);
+IDDefSwitch (&AltDecPecSw, NULL);
+IDDefSwitch (&AzRaPecSw, NULL);
+IDDefSwitch (&SelenSyncSw, NULL);
+IDDefSwitch (&AltDecBackSlashSw, NULL);
+IDDefSwitch (&AzRaBackSlashSw, NULL);
+IDDefNumber (&OTATemp, NULL);
+IDDefSwitch (&OTAUpdateSw, NULL);
+
+}
+
+void LX200GPS::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+ // ignore if not ours //
+ if (strcmp (dev, thisDevice))
+ return;
+
+ LX200_16::ISNewText (dev, name, texts, names, n);
+}
+
+void LX200GPS::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+
+ LX200_16::ISNewNumber (dev, name, values, names, n);
+
+ }
+
+
+ void LX200GPS::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+ {
+ int index;
+ char msg[64];
+
+ if (strcmp (dev, thisDevice))
+ return;
+
+ /* GPS Power */
+ if (!strcmp(name,GPSPowerSw.name))
+ {
+ if (checkPower(&GPSPowerSw))
+ return;
+
+ IUResetSwitches(&GPSPowerSw);
+ IUUpdateSwitches(&GPSPowerSw, states, names, n);
+ index = getOnSwitch(&GPSPowerSw);
+ index == 0 ? turnGPSOn() : turnGPSOff();
+ GPSPowerSw.s = IPS_OK;
+ IDSetSwitch (&GPSPowerSw, index == 0 ? "GPS System is ON" : "GPS System is OFF" );
+ return;
+ }
+
+ /* GPS Status Update */
+ if (!strcmp(name,GPSStatusSw.name))
+ {
+ if (checkPower(&GPSStatusSw))
+ return;
+
+ IUResetSwitches(&GPSStatusSw);
+ IUUpdateSwitches(&GPSStatusSw, states, names, n);
+ index = getOnSwitch(&GPSStatusSw);
+
+ if (index == 0)
+ {
+ gpsSleep();
+ strcpy(msg, "GPS system is in sleep mode.");
+ }
+ else if (index == 1)
+ {
+ gpsWakeUp();
+ strcpy(msg, "GPS system is reactivated.");
+ }
+ else
+ {
+ gpsRestart();
+ strcpy(msg, "GPS system is restarting...");
+ updateTime();
+ updateLocation();
+ }
+
+ GPSStatusSw.s = IPS_OK;
+ IDSetSwitch (&GPSStatusSw, "%s", msg);
+ return;
+
+ }
+
+ /* GPS Update */
+ if (!strcmp(name,GPSUpdateSw.name))
+ {
+ if (checkPower(&GPSUpdateSw))
+ return;
+
+ GPSUpdateSw.s = IPS_OK;
+ IDSetSwitch(&GPSUpdateSw, "Updating GPS system. This operation might take few minutes to complete...");
+ if (updateGPS_System())
+ {
+ IDSetSwitch(&GPSUpdateSw, "GPS system update successful.");
+ updateTime();
+ updateLocation();
+ }
+ else
+ {
+ GPSUpdateSw.s = IPS_IDLE;
+ IDSetSwitch(&GPSUpdateSw, "GPS system update failed.");
+ }
+ return;
+ }
+
+ /* Alt Dec Periodic Error correction */
+ if (!strcmp(name, AltDecPecSw.name))
+ {
+ if (checkPower(&AltDecPecSw))
+ return;
+
+ IUResetSwitches(&AltDecPecSw);
+ IUUpdateSwitches(&AltDecPecSw, states, names, n);
+ index = getOnSwitch(&AltDecPecSw);
+
+ if (index == 0)
+ {
+ enableDecAltPec();
+ strcpy (msg, "Alt/Dec Compensation Enabled");
+ }
+ else
+ {
+ disableDecAltPec();
+ strcpy (msg, "Alt/Dec Compensation Disabled");
+ }
+
+ AltDecPecSw.s = IPS_OK;
+ IDSetSwitch(&AltDecPecSw, "%s", msg);
+
+ return;
+ }
+
+ /* Az RA periodic error correction */
+ if (!strcmp(name, AzRaPecSw.name))
+ {
+ if (checkPower(&AzRaPecSw))
+ return;
+
+ IUResetSwitches(&AzRaPecSw);
+ IUUpdateSwitches(&AzRaPecSw, states, names, n);
+ index = getOnSwitch(&AzRaPecSw);
+
+ if (index == 0)
+ {
+ enableRaAzPec();
+ strcpy (msg, "Ra/Az Compensation Enabled");
+ }
+ else
+ {
+ disableRaAzPec();
+ strcpy (msg, "Ra/Az Compensation Disabled");
+ }
+
+ AzRaPecSw.s = IPS_OK;
+ IDSetSwitch(&AzRaPecSw, "%s", msg);
+
+ return;
+ }
+
+ if (!strcmp(name, AltDecBackSlashSw.name))
+ {
+ if (checkPower(&AltDecBackSlashSw))
+ return;
+
+ activateAltDecAntiBackSlash();
+ AltDecBackSlashSw.s = IPS_OK;
+ IDSetSwitch(&AltDecBackSlashSw, "Alt/Dec Anti-backslash enabled");
+ return;
+ }
+
+ if (!strcmp(name, AzRaBackSlashSw.name))
+ {
+ if (checkPower(&AzRaBackSlashSw))
+ return;
+
+ activateAzRaAntiBackSlash();
+ AzRaBackSlashSw.s = IPS_OK;
+ IDSetSwitch(&AzRaBackSlashSw, "Az/Ra Anti-backslash enabled");
+ return;
+ }
+
+ if (!strcmp(name, OTAUpdateSw.name))
+ {
+ if (checkPower(&OTAUpdateSw))
+ return;
+
+ IUResetSwitches(&OTAUpdateSw);
+
+ if (getOTATemp(&OTATemp.np[0].value) < 0)
+ {
+ OTATemp.s = IPS_ALERT;
+ IDSetNumber(&OTATemp, "Error: OTA temperature read timed out.");
+ }
+ else
+ {
+ OTATemp.s = IPS_OK;
+ IDSetNumber(&OTATemp, NULL);
+ }
+
+ return;
+ }
+
+
+
+ LX200_16::ISNewSwitch (dev, name, states, names, n);
+
+}
+
+ void LX200GPS::ISPoll ()
+ {
+
+ LX200_16::ISPoll();
+
+
+ }
+
+ void updateTemp(void * /*p*/)
+ {
+
+ if (telescope->isTelescopeOn())
+ {
+ if (getOTATemp(&OTATemp.np[0].value) < 0)
+ {
+ OTATemp.s = IPS_ALERT;
+ IDSetNumber(&OTATemp, "Error: OTA temperature read timed out.");
+ return;
+ }
+ else
+ {
+ OTATemp.s = IPS_OK;
+ IDSetNumber(&OTATemp, NULL);
+ }
+ }
+
+ IEAddTimer(900000, updateTemp, NULL);
+
+ }
+
+ void LX200GPS::getBasicData()
+ {
+
+ //getOTATemp(&OTATemp.np[0].value);
+ //IDSetNumber(&OTATemp, NULL);
+
+ // process parent
+ LX200_16::getBasicData();
+ }
+
diff --git a/kstars/kstars/indi/lx200gps.h b/kstars/kstars/indi/lx200gps.h
new file mode 100644
index 00000000..7d1ef476
--- /dev/null
+++ b/kstars/kstars/indi/lx200gps.h
@@ -0,0 +1,45 @@
+#ifndef LX200GPS_H
+#define LX200GPS_H
+
+/*
+ LX200 GPS
+ Copyright (C) 2003 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include "lx200_16.h"
+
+class LX200GPS : public LX200_16
+{
+ public:
+ LX200GPS();
+ ~LX200GPS() {}
+
+ void ISGetProperties (const char *dev);
+ void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+ void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+ void ISPoll ();
+ void getBasicData();
+
+};
+
+void changeLX200GPSDeviceName(const char *newName);
+
+#endif
+
+
diff --git a/kstars/kstars/indi/sbigccd.cpp b/kstars/kstars/indi/sbigccd.cpp
new file mode 100644
index 00000000..fb35cf59
--- /dev/null
+++ b/kstars/kstars/indi/sbigccd.cpp
@@ -0,0 +1,884 @@
+#if 0
+ INDI driver for SBIG CCD
+ Copyright (C) 2005 Chris Curran (ccurran AT planetcurran DOT com)
+
+ Based on Apogee PPI driver by Jasem Mutlaq (mutlaqja AT ikarustech DOT com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include <ctype.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <zlib.h>
+
+#include "sbigccd.h"
+#include "lilxml.h"
+#include "base64.h"
+
+extern char* me; /* argv[0] */
+SBIGCam *MainCam = NULL; /* Main and only camera */
+
+/* send client definitions of all properties */
+void ISInit()
+{
+ if (MainCam == NULL)
+ MainCam = new SBIGCam();
+}
+
+void ISGetProperties (const char *dev)
+{
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ ISInit();
+
+ MainCam->ISGetProperties(dev);
+}
+
+
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+
+ /* ignore if not ours */
+ if (dev && strcmp (dev, mydev))
+ return;
+
+ ISInit();
+
+ MainCam->ISNewSwitch(dev, name, states, names, n);
+}
+
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+ /* ignore if not ours */
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ ISInit();
+
+ MainCam->ISNewText(dev, name, texts, names, n);
+}
+
+
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+
+ /* ignore if not ours */
+ if (dev && strcmp (dev, mydev))
+ return;
+
+ ISInit();
+
+ MainCam->ISNewNumber(dev, name, values, names, n);
+}
+
+void ISNewBLOB (const char */*dev*/, const char */*name*/, int */*sizes[]*/, char **/*blobs[]*/, char **/*formats[]*/, char **/*names[]*/, int /*n*/)
+{
+
+ // We use this if we're receving binary data from the client. Most likely we won't for this driver.
+
+}
+
+SBIGCam::SBIGCam()
+{
+ initProperties();
+ IEAddTimer (POLLMS, SBIGCam::ISStaticPoll, this);
+}
+
+SBIGCam::~SBIGCam()
+{
+
+}
+
+void SBIGCam::initProperties()
+{
+ fillSwitch(&PowerS[0], "CONNECT", "Connect", ISS_OFF);
+ fillSwitch(&PowerS[1], "DISCONNECT", "Disconnect", ISS_ON);
+ fillSwitchVector(&PowerSP, PowerS, NARRAY(PowerS), mydev, "CONNECTION", "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
+
+ fillSwitch(&FrameTypeS[0], "FRAME_LIGHT", "Light", ISS_ON);
+ fillSwitch(&FrameTypeS[1], "FRAME_BIAS", "Bias", ISS_OFF);
+ fillSwitch(&FrameTypeS[2], "FRAME_DARK", "Dark", ISS_OFF);
+ fillSwitch(&FrameTypeS[3], "FRAME_FLAT", "Flat Field", ISS_OFF);
+ fillSwitchVector(&FrameTypeSP, FrameTypeS, NARRAY(FrameTypeS), mydev, "CCD_FRAME_TYPE", "Frame Type", EXPOSE_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
+
+ fillNumber(&FrameN[0], "X", "X", "%.0f", 0., MAX_PIXELS, 1., 0.);
+ fillNumber(&FrameN[1], "Y", "Y", "%.0f", 0., MAX_PIXELS, 1., 0.);
+ fillNumber(&FrameN[2], "WIDTH", "Width", "%.0f", 0., MAX_PIXELS, 1., 0.);
+ fillNumber(&FrameN[3], "HEIGHT", "Height", "%.0f", 0., MAX_PIXELS, 1., 0.);
+ fillNumberVector(&FrameNP, FrameN, NARRAY(FrameN), mydev, "CCD_FRAME", "Frame", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
+
+ fillNumber(&BinningN[0], "HOR_BIN", "X", "%0.f", 1., MAXHBIN, 1., 1.);
+ fillNumber(&BinningN[1], "VER_BIN", "Y", "%0.f", 1., MAXVBIN, 1., 1.);
+ fillNumberVector(&BinningNP, BinningN, NARRAY(BinningN), mydev, "CCD_BINNING", "Binning", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
+
+ fillNumber(&ExposeTimeN[0], "EXPOSE_DURATION", "Duration (s)", "%5.2f", 0., 36000., 0.5, 1.);
+ fillNumberVector(&ExposeTimeNP, ExposeTimeN, NARRAY(ExposeTimeN), mydev, "CCD_EXPOSE_DURATION", "Expose", EXPOSE_GROUP, IP_RW, 60, IPS_IDLE);
+
+ fillNumber(&TemperatureN[0], "TEMPERATURE", "Temperature", "%+06.2f", MIN_CCD_TEMP, MAX_CCD_TEMP, 0.2, 0.);
+ fillNumberVector(&TemperatureNP, TemperatureN, NARRAY(TemperatureN), mydev, "CCD_TEMPERATURE", "Expose", EXPOSE_GROUP, IP_RW, 60, IPS_IDLE);
+
+ // We need to setup the BLOB (Binary Large Object) below. Using this property, we can send FITS to our client
+ strcpy(imageB.name, "CCD1");
+ strcpy(imageB.label, "Feed");
+ strcpy(imageB.format, "");
+ imageB.blob = 0;
+ imageB.bloblen = 0;
+ imageB.size = 0;
+ imageB.bvp = 0;
+ imageB.aux0 = 0;
+ imageB.aux1 = 0;
+ imageB.aux2 = 0;
+
+ strcpy(imageBP.device, mydev);
+ strcpy(imageBP.name, "Video");
+ strcpy(imageBP.label, "Video");
+ strcpy(imageBP.group, COMM_GROUP);
+ strcpy(imageBP.timestamp, "");
+ imageBP.p = IP_RO;
+ imageBP.timeout = 0;
+ imageBP.s = IPS_IDLE;
+ imageBP.bp = &imageB;
+ imageBP.nbp = 1;
+ imageBP.aux = 0;
+
+}
+
+void SBIGCam::ISGetProperties(const char */*dev*/)
+{
+
+ /* COMM_GROUP */
+ IDDefSwitch(&PowerSP, NULL);
+ IDDefBLOB(&imageBP, NULL);
+
+ /* Expose */
+ IDDefSwitch(&FrameTypeSP, NULL);
+ IDDefNumber(&ExposeTimeNP, NULL);
+ IDDefNumber(&TemperatureNP, NULL);
+
+ /* Image Group */
+ IDDefNumber(&FrameNP, NULL);
+ IDDefNumber(&BinningNP, NULL);
+
+}
+
+void SBIGCam::ISNewSwitch (const char */*dev*/, const char *name, ISState *states, char *names[], int n)
+{
+
+ /* Connection */
+ if (!strcmp (name, PowerSP.name))
+ {
+ IUResetSwitches(&PowerSP);
+ IUUpdateSwitches(&PowerSP, states, names, n);
+ connectCCD();
+ return;
+ }
+
+ /* Frame Type */
+ if (!strcmp(FrameTypeSP.name, name))
+ {
+ if (checkPowerS(&FrameTypeSP))
+ return;
+
+ IUResetSwitches(&FrameTypeSP);
+ IUUpdateSwitches(&FrameTypeSP, states, names, n);
+ FrameTypeSP.s = IPS_OK;
+ IDSetSwitch(&FrameTypeSP, NULL);
+
+ return;
+ }
+
+}
+
+void SBIGCam::ISNewText (const char */*dev*/, const char */*name*/, char **/*texts[]*/, char **/*names[]*/, int /*n*/)
+{
+
+}
+
+void SBIGCam::ISNewNumber (const char */*dev*/, const char *name, double values[], char *names[], int n)
+{
+ /* Exposure time */
+ if (!strcmp (ExposeTimeNP.name, name))
+ {
+ if (checkPowerN(&ExposeTimeNP))
+ return;
+
+ if (ExposeTimeNP.s == IPS_BUSY)
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ ExposeTimeN[0].value = 0;
+
+ IDSetNumber(&ExposeTimeNP, "Exposure cancelled.");
+ IDLog("Exposure Cancelled.\n");
+ return;
+ }
+
+ ExposeTimeNP.s = IPS_IDLE;
+
+ IUUpdateNumbers(&ExposeTimeNP, values, names, n);
+
+ IDLog("Exposure Time (ms) is: %g\n", ExposeTimeN[0].value);
+
+ handleExposure(NULL);
+ return;
+ }
+
+ if (!strcmp(TemperatureNP.name, name))
+ {
+ if (checkPowerN(&TemperatureNP))
+ return;
+
+ TemperatureNP.s = IPS_IDLE;
+
+ if (values[0] < MIN_CCD_TEMP || values[0] > MAX_CCD_TEMP)
+ {
+ IDSetNumber(&TemperatureNP, "Error: valid range of temperature is from %d to %d", MIN_CCD_TEMP, MAX_CCD_TEMP);
+ return;
+ }
+
+ targetTemp = values[0];
+
+ // JM: Below, tell SBIG to update to temperature to targetTemp
+ // e.g. cam->setTemp(targetTemp);
+
+
+ // Now we set property to busy and poll in ISPoll for CCD temp
+ TemperatureNP.s = IPS_BUSY;
+
+ IDSetNumber(&TemperatureNP, "Setting CCD temperature to %+06.2f C", values[0]);
+ IDLog("Setting CCD temperature to %+06.2f C\n", values[0]);
+ return;
+ }
+
+ // Subframing
+ if (!strcmp(FrameNP.name, name))
+ {
+ if (checkPowerN(&FrameNP))
+ return;
+
+ FrameNP.s = IPS_OK;
+ IUUpdateNumbers(&FrameNP, values, names, n);
+
+ // JM: Below, we setup the frame size we want to take exposure of
+ // The way it is done depends on the camera API. Example below
+ //cam->m_StartX = (int) FrameN[0].value;
+ //cam->m_StartY = (int) FrameN[1].value;
+ //cam->m_Width = (int) FrameN[2].value;
+ //cam->m_Height = (int) FrameN[3].value;
+
+ IDSetNumber(&FrameNP, NULL);
+
+ } /* end FrameNP */
+
+
+ // Binning
+ if (!strcmp(BinningNP.name, name))
+ {
+ if (checkPowerN(&BinningNP))
+ return;
+
+
+ BinningNP.s = IPS_OK;
+ IUUpdateNumbers(&BinningNP, values, names, n);
+
+ // JM: Below we set the camera binning.
+ // eg:
+ //cam->m_BinX = (int) BinningN[0].value;
+ //cam->m_BinY = (int) BinningN[1].value;
+
+ IDLog("Binning is: %.0f x %.0f\n", BinningN[0].value, BinningN[1].value);
+ return;
+ }
+}
+
+
+void SBIGCam::ISStaticPoll(void *p)
+{
+ if (!((SBIGCam *)p)->isCCDConnected())
+ {
+ IEAddTimer (POLLMS, SBIGCam::ISStaticPoll, p);
+ return;
+ }
+
+ ((SBIGCam *) p)->ISPoll();
+
+ IEAddTimer (POLLMS, SBIGCam::ISStaticPoll, p);
+}
+
+void SBIGCam::ISPoll()
+{
+ static int mtc=5;
+ int readStatus=0;
+ double ccdTemp (0);
+
+ switch (ExposeTimeNP.s)
+ {
+ case IPS_IDLE:
+ case IPS_OK:
+ break;
+
+ case IPS_BUSY:
+
+ // JM: Here we check the status of the camera (whether it's still capturing an image or has finished that)
+ // ISPoll is called once per second. e.g. below for how we do this for Apogee Cameras
+ /*
+ readStatus = cam->read_Status();
+ if (readStatus < 0)
+ {
+ IDLog("Error in exposure!\n");
+ ExposeTimeNP.s = IPS_IDLE;
+ ExposeTimeN[0].value = 0;
+ IDSetNumber(&ExposeTimeNP, "Error in exposure procedure.");
+ return;
+ }
+ else if (readStatus == Camera_Status_ImageReady)
+ {
+ ExposeTimeN[0].value = 0;
+ ExposeTimeNP.s = IPS_OK;
+ IDSetNumber(&ExposeTimeNP, "Exposure done, downloading image...");
+ IDLog("Exposure done, downloading image...\n");
+ // grab and save image. Don't forget to call this!
+ grabImage();
+ return;
+ } */
+
+ ExposeTimeN[0].value --;
+ IDSetNumber(&ExposeTimeNP, NULL);
+ break;
+
+ case IPS_ALERT:
+ break;
+ }
+
+
+ switch (TemperatureNP.s)
+ {
+ // JM: If we're not setting a new temperature (i.e. state is either ok or idle)
+ // We simply check for the temp every 5 seconds (this is why mtc = 5 and then decremented).
+ case IPS_IDLE:
+ case IPS_OK:
+ mtc--;
+
+ if (mtc == 0)
+ {
+ //TemperatureN[0].value = cam->read_Temperature();
+ IDSetNumber(&TemperatureNP, NULL);
+ mtc = 5;
+ }
+ break;
+
+ // JM: If we're setting a new temperature, we continously check for it here untill we get
+ // a "close enough" value. This close enough value as seen below is the TEMP_THRESHOLD (0.25 C)
+ case IPS_BUSY:
+
+ // Read in current CCD temp
+ //ccdTemp = cam->read_Temperature();
+
+ if (fabs(targetTemp - ccdTemp) <= TEMP_THRESHOLD)
+ TemperatureNP.s = IPS_OK;
+
+ mtc = 1;
+ TemperatureN[0].value = ccdTemp;
+ IDSetNumber(&TemperatureNP, NULL);
+ break;
+
+ case IPS_ALERT:
+ break;
+ }
+
+}
+
+/* Downloads the image from the CCD row by row and store them
+ in a raw file.
+ N.B. No processing is done on the image */
+void SBIGCam::grabImage()
+{
+
+ long err;
+ int img_size, fd;
+ char errmsg[1024];
+ char filename[] = "/tmp/fitsXXXXXX";
+
+ if ((fd = mkstemp(filename)) < 0)
+ {
+ IDMessage(mydev, "Error making temporary filename.");
+ IDLog("Error making temporary filename.\n");
+ return;
+ }
+ close(fd);
+
+ // JM: allocate memory for buffer. In most cameras, the bit depth is 16 bit and so we use unsigned short
+ // But change if the bit depth is different
+ img_size = SBIGFrame.width * SBIGFrame.height * sizeof(unsigned short);
+
+ SBIGFrame.img = (unsigned short *) malloc (img_size);
+
+ if (SBIGFrame.img == NULL)
+ {
+ IDMessage(mydev, "Not enough memory to store image.");
+ IDLog("Not enough memory to store image.\n");
+ return;
+ }
+
+ // JM: Here we fetch the image from the camera
+ //
+ /*if (!cam->GetImage( SBIGFrame.img , SBIGFrame.width, SBIGFrame.height ))
+ {
+ free(SBIGFrame.img);
+ IDMessage(mydev, "GetImage() failed.");
+ IDLog("GetImage() failed.");
+ return;
+ }*/
+
+ err = writeFITS(filename, errmsg);
+
+ if (err)
+ {
+ free(SBIGFrame.img);
+ IDMessage(mydev, errmsg, NULL);
+ return;
+ }
+
+ free(SBIGFrame.img);
+
+}
+
+int SBIGCam::writeFITS(char *filename, char errmsg[])
+{
+
+ FITS_FILE* ofp;
+ int bpp, bpsl, width, height;
+ long nbytes;
+ FITS_HDU_LIST *hdu;
+
+ ofp = fits_open (filename, "w");
+ if (!ofp)
+ {
+ sprintf(errmsg, "Error: cannot open file for writing.");
+ return (-1);
+ }
+
+ // We're assuming bit depth is 16 (unsigned short). Change as desired.
+ width = SBIGFrame.width;
+ height = SBIGFrame.height;
+ bpp = sizeof(unsigned short); /* Bytes per Pixel */
+ bpsl = bpp * SBIGFrame.width; /* Bytes per Line */
+ nbytes = 0;
+
+ hdu = create_fits_header (ofp, width, height, bpp);
+ if (hdu == NULL)
+ {
+ sprintf(errmsg, "Error: creating FITS header failed.");
+ return (-1);
+ }
+ if (fits_write_header (ofp, hdu) < 0)
+ {
+ sprintf(errmsg, "Error: writing to FITS header failed.");
+ return (-1);
+ }
+
+ // JM: Here we're performing little endian to big endian (network order) conversion
+ // Since FITS is stored in big endian. If the camera provides the image buffer in big endian
+ // then there is no need for this conversion
+ for (int i=0; i < height; i++)
+ for (int j=0 ; j < width; j++)
+ SBIGFrame.img[width * i + j] = getBigEndian( (SBIGFrame.img[width * i + j]) );
+
+ // The "2" below is for two bytes (16 bit or unsigned short). Again, change as desired.
+ for (int i= 0; i < height ; i++)
+ {
+ fwrite(SBIGFrame.img + (i * width), 2, width, ofp->fp);
+ nbytes += bpsl;
+ }
+
+ nbytes = nbytes % FITS_RECORD_SIZE;
+ if (nbytes)
+ {
+ while (nbytes++ < FITS_RECORD_SIZE)
+ putc (0, ofp->fp);
+ }
+
+ if (ferror (ofp->fp))
+ {
+ sprintf(errmsg, "Error: write error occured");
+ return (-1);
+ }
+
+ fits_close (ofp);
+
+ /* Success */
+ ExposeTimeNP.s = IPS_OK;
+ IDSetNumber(&ExposeTimeNP, NULL);
+ IDLog("Loading FITS image...\n");
+
+ uploadFile(filename);
+
+ return 0;
+
+}
+
+void SBIGCam::uploadFile(char * filename)
+{
+
+ FILE * fitsFile;
+ unsigned char *fitsData, *compressedData;
+ int r=0;
+ unsigned int i =0, nr = 0;
+ uLongf compressedBytes=0;
+ uLong totalBytes;
+ struct stat stat_p;
+
+ if ( -1 == stat (filename, &stat_p))
+ {
+ IDLog(" Error occoured attempting to stat %s\n", filename);
+ return;
+ }
+
+ totalBytes = stat_p.st_size;
+ fitsData = (unsigned char *) malloc (sizeof(unsigned char) * totalBytes);
+ compressedData = (unsigned char *) malloc (sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
+
+ if (fitsData == NULL || compressedData == NULL)
+ {
+ IDLog("Error! low memory. Unable to initialize fits buffers.\n");
+ return;
+ }
+
+ fitsFile = fopen(filename, "r");
+
+ if (fitsFile == NULL)
+ return;
+
+ /* #1 Read file from disk */
+ for (i=0; i < totalBytes; i+= nr)
+ {
+ nr = fread(fitsData + i, 1, totalBytes - i, fitsFile);
+
+ if (nr <= 0)
+ {
+ IDLog("Error reading temporary FITS file.\n");
+ return;
+ }
+ }
+
+ compressedBytes = sizeof(char) * totalBytes + totalBytes / 64 + 16 + 3;
+
+ /* #2 Compress it */
+ r = compress2(compressedData, &compressedBytes, fitsData, totalBytes, 9);
+ if (r != Z_OK)
+ {
+ /* this should NEVER happen */
+ IDLog("internal error - compression failed: %d\n", r);
+ return;
+ }
+
+ /* #3 Send it */
+ imageB.blob = compressedData;
+ imageB.bloblen = compressedBytes;
+ imageB.size = totalBytes;
+ strcpy(imageB.format, ".fits.z");
+ imageBP.s = IPS_OK;
+ IDSetBLOB (&imageBP, NULL);
+
+ free (fitsData);
+ free (compressedData);
+
+}
+
+/* Initiates the exposure procedure */
+void SBIGCam::handleExposure(void */*p*/)
+{
+
+ int curFrame = getOnSwitch(&FrameTypeSP);
+
+ switch (curFrame)
+ {
+ /* Light frame */
+ case LIGHT_FRAME:
+
+ /*if (!cam->Expose( (int) ExposeTimeN[0].value, true ))
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ IDSetNumber(&ExposeTimeNP, "Light Camera exposure failed.");
+ IDLog("Light Camera exposure failed.\n");
+ return;
+ }*/
+ break;
+
+ /* BIAS frame is the same as DARK but with minimum period. i.e. readout from camera electronics.
+ */
+ case BIAS_FRAME:
+
+ /*if (!cam->Expose( 0.05 , false ))
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ IDSetNumber(&ExposeTimeNP, "Bias Camera exposure failed.");
+ IDLog("Bias Camera exposure failed.\n");
+ return;
+ }*/
+ break;
+
+ /* Dark frame */
+ case DARK_FRAME:
+
+ /*if (!cam->Expose( (int) ExposeTimeN[0].value , false ))
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ IDSetNumber(&ExposeTimeNP, "Dark Camera exposure failed.");
+ IDLog("Dark Camera exposure failed.\n");
+ return;
+ }*/
+ break;
+
+ case FLAT_FRAME:
+
+ /*if (!cam->Expose( (int) ExposeTimeN[0].value , true ))
+ {
+ ExposeTimeNP.s = IPS_IDLE;
+ IDSetNumber(&ExposeTimeNP, "Flat Camera exposure failed.");
+ IDLog("Flat Camera exposure failed.\n");
+ return;
+ }*/
+ break;
+ }
+
+ SBIGFrame.frameType = curFrame;
+ SBIGFrame.width = (int) FrameN[2].value;
+ SBIGFrame.height = (int) FrameN[3].value;
+ SBIGFrame.expose = (int) ExposeTimeN[0].value;
+ SBIGFrame.temperature = TemperatureN[0].value;
+ SBIGFrame.binX = (int) BinningN[0].value;
+ SBIGFrame.binY = (int) BinningN[1].value;
+
+ ExposeTimeNP.s = IPS_BUSY;
+
+ IDSetNumber(&ExposeTimeNP, "Taking a %g seconds frame...", ExposeTimeN[0].value);
+ IDLog("Taking a frame...\n");
+
+}
+
+/* Retrieves basic data from the CCD upon connection like temperature, array size, firmware..etc */
+void SBIGCam::getBasicData()
+{
+
+
+ // Maximum resolution
+
+ // JM: Update here basic variables upon connection.
+
+ /*
+ FrameN[2].max = cam->m_NumX;
+ FrameN[3].max = cam->m_NumY;
+ IUUpdateMinMax(&FrameNP);
+
+ // Maximum Bin
+ BinningN[0].max = cam->m_MaxBinX;
+ BinningN[1].max = cam->m_MaxBinX;
+ IUUpdateMinMax(&BinningNP);
+
+ // Current Temperature
+ TemperatureN[0].value = cam->read_Temperature();
+ IDSetNumber(&TemperatureNP, NULL);*/
+
+}
+
+int SBIGCam::getOnSwitch(ISwitchVectorProperty *sp)
+{
+ for (int i=0; i < sp->nsp ; i++)
+ {
+ if (sp->sp[i].s == ISS_ON)
+ return i;
+ }
+
+ return -1;
+}
+
+int SBIGCam::checkPowerS(ISwitchVectorProperty *sp)
+{
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(sp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", sp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", sp->label);
+
+ sp->s = IPS_IDLE;
+ IDSetSwitch(sp, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int SBIGCam::checkPowerN(INumberVectorProperty *np)
+{
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(np->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", np->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", np->label);
+
+ np->s = IPS_IDLE;
+ IDSetNumber(np, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int SBIGCam::checkPowerT(ITextVectorProperty *tp)
+{
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(tp->label, ""))
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", tp->name);
+ else
+ IDMessage (mydev, "Cannot change property %s while the CCD is offline.", tp->label);
+
+ tp->s = IPS_IDLE;
+ IDSetText(tp, NULL);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+void SBIGCam::connectCCD()
+{
+
+ switch (PowerS[0].s)
+ {
+ case ISS_ON:
+ if (initCamera())
+ {
+ /* Sucess! */
+ PowerS[0].s = ISS_ON;
+ PowerS[1].s = ISS_OFF;
+ PowerSP.s = IPS_OK;
+ IDSetSwitch(&PowerSP, "CCD is online. Retrieving basic data.");
+ IDLog("CCD is online. Retrieving basic data.\n");
+ getBasicData();
+
+ }
+ else
+ {
+ PowerSP.s = IPS_IDLE;
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch(&PowerSP, "Error: no cameras were detected.");
+ IDLog("Error: no cameras were detected.\n");
+ return;
+ }
+
+ break;
+
+ case ISS_OFF:
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_IDLE;
+ IDSetSwitch(&PowerSP, "CCD is offline.");
+
+ // JM: Disconnect cam and clean up
+ // e.g. disConnectSBIG();
+ break;
+ }
+
+}
+
+bool SBIGCam::initCamera()
+{
+ // JM: Here, we do all camera initilization stuff and we establish a connection to the camera
+ // If everything goes well, we return true, otherwise false
+ // Please use IDLog(...) to report errors.
+
+ return false;
+}
+
+/* isCCDConnected: return 1 if we have a connection, 0 otherwise */
+int SBIGCam::isCCDConnected(void)
+{
+ return ((PowerS[0].s == ISS_ON) ? 1 : 0);
+}
+
+FITS_HDU_LIST * SBIGCam::create_fits_header (FITS_FILE *ofp, uint width, uint height, uint bpp)
+{
+
+ FITS_HDU_LIST *hdulist;
+
+ char temp_s[FITS_CARD_SIZE], expose_s[FITS_CARD_SIZE], binning_s[FITS_CARD_SIZE], pixel_s[FITS_CARD_SIZE], frame_s[FITS_CARD_SIZE];
+ char obsDate[FITS_CARD_SIZE];
+
+ snprintf(obsDate, FITS_CARD_SIZE, "DATE-OBS= '%s' /Observation Date UTC", timestamp());
+
+ hdulist = fits_add_hdu (ofp);
+ if (hdulist == NULL) return (NULL);
+
+ hdulist->used.simple = 1;
+ hdulist->bitpix = 16;
+ hdulist->naxis = 2;
+ hdulist->naxisn[0] = width;
+ hdulist->naxisn[1] = height;
+ hdulist->naxisn[2] = bpp;
+ // JM: Record here the minimum and maximum pixel values
+ /*hdulist->used.datamin = min();
+ hdulist->datamin = min();
+ hdulist->used.datamax = max();
+ hdulist->datamax = max();*/
+ hdulist->used.bzero = 1;
+ hdulist->bzero = 0.0;
+ hdulist->used.bscale = 1;
+ hdulist->bscale = 1.0;
+
+ snprintf(temp_s, FITS_CARD_SIZE, "CCD-TEMP= %g / degrees celcius", SBIGFrame.temperature);
+ snprintf(expose_s, FITS_CARD_SIZE, "EXPOSURE= %d / milliseconds", SBIGFrame.expose);
+ snprintf(binning_s, FITS_CARD_SIZE, "BINNING = '(%d x %d)'", SBIGFrame.binX, SBIGFrame.binY);
+ //sprintf(pixel_s, "PIX-SIZ = '%.0f microns square'", PixelSizeN[0].value);
+ switch (SBIGFrame.frameType)
+ {
+ case LIGHT_FRAME:
+ strcpy(frame_s, "FRAME = 'Light'");
+ break;
+ case BIAS_FRAME:
+ strcpy(frame_s, "FRAME = 'Bias'");
+ break;
+ case FLAT_FRAME:
+ strcpy(frame_s, "FRAME = 'Flat Field'");
+ break;
+ case DARK_FRAME:
+ strcpy(frame_s, "FRAME = 'Dark'");
+ break;
+ }
+
+ fits_add_card (hdulist, frame_s);
+ fits_add_card (hdulist, temp_s);
+ fits_add_card (hdulist, expose_s);
+ //fits_add_card (hdulist, pixel_s);
+
+ // JM: If there is a way to get the specific model of the camera, use that.
+ fits_add_card (hdulist, "INSTRUME= 'SBIG CCD'");
+ fits_add_card (hdulist, obsDate);
+
+ return (hdulist);
+}
+
diff --git a/kstars/kstars/indi/sbigccd.h b/kstars/kstars/indi/sbigccd.h
new file mode 100644
index 00000000..5aa650f1
--- /dev/null
+++ b/kstars/kstars/indi/sbigccd.h
@@ -0,0 +1,147 @@
+#if 0
+ INDI driver for SBIG CCD
+ Copyright (C) 2005 Chris Curran (ccurran AT planetcurran DOT com)
+
+ Based on Apogee PPI driver by Jasem Mutlaq (mutlaqja AT ikarustech DOT com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#ifndef SBIGCCD_H
+#define SBIGCCD_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "fitsrw.h"
+#include "indidevapi.h"
+#include "eventloop.h"
+#include "indicom.h"
+
+#define mydev "SBIG CCD"
+
+#define COMM_GROUP "Communication"
+#define EXPOSE_GROUP "Expose"
+#define IMAGE_GROUP "Image Settings"
+
+#define POLLMS 1000 /* Polling time (ms) */
+#define TEMP_THRESHOLD .25 /* Differential temperature threshold (C)*/
+
+#define MAX_PIXELS 4096
+#define MAXHBIN 8
+#define MAXVBIN 64
+#define MIN_CCD_TEMP -60
+#define MAX_CCD_TEMP 40
+
+#define getBigEndian(p) ( ((p & 0xff) << 8) | (p >> 8))
+
+class SBIGCam {
+
+ public:
+
+ SBIGCam();
+ ~SBIGCam();
+
+ /* INDI Functions that must be called from indidrivermain */
+ void ISGetProperties (const char *dev);
+ void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+ void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+
+ private:
+
+ /* Structs */
+ struct
+ {
+ short width;
+ short height;
+ int frameType;
+ int expose;
+ double temperature;
+ int binX, binY;
+ unsigned short *img;
+ } SBIGFrame;
+
+ enum { LIGHT_FRAME , BIAS_FRAME, DARK_FRAME, FLAT_FRAME };
+
+ /* Switches */
+ ISwitch PowerS[2];
+ ISwitch FrameTypeS[4];
+
+ /* Numbers */
+ INumber FrameN[4];
+ INumber BinningN[2];
+ INumber ExposeTimeN[1];
+ INumber TemperatureN[1];
+
+ /* BLOBs */
+ IBLOB imageB;
+
+ /* Switch vectors */
+ ISwitchVectorProperty PowerSP; /* Connection switch */
+ ISwitchVectorProperty FrameTypeSP; /* Frame type */
+
+ /* Number vectors */
+ INumberVectorProperty FrameNP; /* Frame specs */
+ INumberVectorProperty BinningNP; /* Binning */
+ INumberVectorProperty ExposeTimeNP; /* Exposure */
+ INumberVectorProperty TemperatureNP; /* Temperature control */
+
+
+ /* BLOB vectors */
+ IBLOBVectorProperty imageBP; /* Data stream */
+
+ /* Other */
+ double targetTemp; /* Target temperature */
+
+ /* Functions */
+
+ /* General */
+ void initProperties();
+ bool initCamera();
+
+ /* CCD */
+ void getBasicData(void);
+ void handleExposure(void *);
+ void connectCCD(void);
+ void uploadFile(char * filename);
+ int writeFITS(char *filename, char errmsg[]);
+ void grabImage(void);
+ int isCCDConnected(void);
+
+ /* Power */
+ int checkPowerS(ISwitchVectorProperty *sp);
+ int checkPowerN(INumberVectorProperty *np);
+ int checkPowerT(ITextVectorProperty *tp);
+
+ /* Helper functions */
+ int manageDefaults(char errmsg[]);
+ int getOnSwitch(ISwitchVectorProperty *sp);
+ FITS_HDU_LIST * create_fits_header (FITS_FILE *ofp, uint width, uint height, uint bpp);
+ static void ISStaticPoll(void *);
+ void ISPoll();
+
+};
+
+#endif
+
diff --git a/kstars/kstars/indi/skycommander.c b/kstars/kstars/indi/skycommander.c
new file mode 100644
index 00000000..261b6808
--- /dev/null
+++ b/kstars/kstars/indi/skycommander.c
@@ -0,0 +1,185 @@
+#if 0
+ Sky Commander INDI driver
+ Copyright (C) 2005 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "indidevapi.h"
+#include "indicom.h"
+#include "lx200driver.h"
+
+#define mydev "Sky Commander"
+#define BASIC_GROUP "Main Control"
+#define POLLMS 1000
+#define currentRA eq[0].value
+#define currentDEC eq[1].value
+
+static void ISPoll(void *);
+static void ISInit(void);
+static void connectTelescope(void);
+
+static ISwitch PowerS[] = {{"CONNECT" , "Connect" , ISS_OFF, 0, 0},{"DISCONNECT", "Disconnect", ISS_ON, 0, 0}};
+ISwitchVectorProperty PowerSP = { mydev, "CONNECTION" , "Connection", BASIC_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, PowerS, NARRAY(PowerS), "", 0};
+
+static IText PortT[] = {{"PORT", "Port", 0, 0, 0, 0}};
+static ITextVectorProperty PortTP = { mydev, "DEVICE_PORT", "Ports", BASIC_GROUP, IP_RW, 0, IPS_IDLE, PortT, NARRAY(PortT), "", 0};
+
+/* equatorial position */
+INumber eq[] = {
+ {"RA", "RA H:M:S", "%10.6m", 0., 24., 0., 0., 0, 0, 0},
+ {"DEC", "Dec D:M:S", "%10.6m", -90., 90., 0., 0., 0, 0, 0},
+};
+INumberVectorProperty eqNum = {
+ mydev, "EQUATORIAL_EOD_COORD", "Equatorial JNow", BASIC_GROUP, IP_RO, 0, IPS_IDLE,
+ eq, NARRAY(eq), "", 0};
+
+
+void ISInit(void)
+{
+ static int isInit=0;
+
+ if (isInit) return;
+
+ isInit = 1;
+
+ IEAddTimer (POLLMS, ISPoll, NULL);
+
+}
+
+void ISGetProperties (const char *dev)
+{
+
+ ISInit();
+
+ dev=dev;
+
+ IDDefSwitch(&PowerSP, NULL);
+ IDDefText(&PortTP, NULL);
+ IDDefNumber(&eqNum, NULL);
+}
+
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ ISInit();
+
+ dev = dev;
+
+ if (!strcmp(name, PowerSP.name))
+ {
+ IUResetSwitches(&PowerSP);
+ IUUpdateSwitches(&PowerSP, states, names, n);
+ connectTelescope();
+ return;
+ }
+}
+
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+
+ ISInit();
+
+ dev=dev; names=names; n=n;
+
+ if (!strcmp(name, PortTP.name))
+ {
+ IUSaveText(&PortT[0], texts[0]);
+ PortTP.s = IPS_OK;
+ IDSetText(&PortTP, NULL);
+ return;
+ }
+
+}
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ dev=dev;name=name;values=values;names=names;n=n;
+}
+
+void ISNewBLOB (const char *dev, const char *name, int sizes[], char *blobs[], char *formats[], char *names[], int n)
+{
+ dev=dev;name=name;sizes=sizes;blobs=blobs;formats=formats;names=names;n=n;
+}
+
+void ISPoll (void *p)
+{
+ p=p;
+
+ if (PowerS[0].s == ISS_ON)
+ {
+ switch (eqNum.s)
+ {
+ case IPS_IDLE:
+ case IPS_OK:
+ case IPS_BUSY:
+ if (updateSkyCommanderCoord(&currentRA, &currentDEC) < 0)
+ {
+ eqNum.s = IPS_ALERT;
+ IDSetNumber(&eqNum, "Unknown error while reading telescope coordinates");
+ IDLog("Unknown error while reading telescope coordinates\n");
+ break;
+ }
+
+ IDSetNumber(&eqNum, NULL);
+ break;
+
+ case IPS_ALERT:
+ break;
+ }
+ }
+
+ IEAddTimer(POLLMS, ISPoll, NULL);
+}
+
+void connectTelescope(void)
+{
+
+ switch (PowerS[0].s)
+ {
+ case ISS_ON:
+ if (Connect(PortT[0].text) < 0)
+ {
+ PowerSP.s = IPS_ALERT;
+ IUResetSwitches(&PowerSP);
+ IDSetSwitch(&PowerSP, "Error connecting to port %s", PortT[0].text);
+ return;
+ }
+
+ PowerSP.s = IPS_OK;
+ IDSetSwitch(&PowerSP, "Sky Commander is online.");
+ break;
+
+ case ISS_OFF:
+ Disconnect();
+ IUResetSwitches(&PowerSP);
+ eqNum.s = PortTP.s = PowerSP.s = IPS_IDLE;
+ IDSetSwitch(&PowerSP, "Sky Commander is offline.");
+ IDSetText(&PortTP, NULL);
+ IDSetNumber(&eqNum, NULL);
+ break;
+ }
+
+}
+
diff --git a/kstars/kstars/indi/temmadriver.c b/kstars/kstars/indi/temmadriver.c
new file mode 100644
index 00000000..55464493
--- /dev/null
+++ b/kstars/kstars/indi/temmadriver.c
@@ -0,0 +1,1000 @@
+#if 0
+ Temma INDI driver
+ Copyright (C) 2004 Francois Meyer (dulle @ free.fr)
+ Remi Petitdemange for the temma protocol
+ Reference site is http://dulle.free.fr/alidade/indi.php
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <time.h>
+
+#include "indicom.h"
+#include "indidevapi.h"
+#include "eventloop.h"
+#include "indicom.h"
+#include "temmadriver.h"
+
+
+ char errormes[][128]={
+ "I/O Timeout",
+ "Error reading from io port",
+ "Error writing to io port",
+ "Unrecognized message"
+ };
+
+char answer[32];
+int fd;
+int read_ret, write_ret;
+unsigned char buffer[256];
+unsigned char buffer2[256];
+
+
+#if 1
+/* Initlization routine */
+static void mountInit()
+{
+ static int inited; /* set once mountInit is called */
+
+ if (inited)
+ return;
+
+ /* setting default comm port */
+ PortT->text = realloc(PortT->text, 10);
+ TemmaNoteT[0].text = realloc( TemmaNoteT[0].text, 64);
+ TemmaNoteT[1].text = realloc( TemmaNoteT[1].text, 64);
+
+ if (!PortT->text || !TemmaNoteT[0].text || !TemmaNoteT[1].text){
+ fprintf(stderr,"Memory allocation error");
+ return;
+ }
+ strcpy(PortT->text, "/dev/ttyS0");
+ strcpy(TemmaNoteT[0].text, "Experimental Driver");
+ strcpy(TemmaNoteT[1].text, "http://dulle.free.fr/alidade/indi.php");
+
+ inited = 1;
+}
+#endif
+
+void ISGetProperties (const char *dev) {
+ if (dev && strcmp (mydev, dev))
+ return;
+
+ mountInit();
+
+ IDDefSwitch (&powSw, NULL);
+ IDDefNumber (&eqTemma, NULL);
+ IDDefNumber (&eqNum, NULL);
+ IDDefSwitch (&OnCoordSetSw, NULL);
+ IDDefSwitch (&abortSlewSw, NULL);
+ IDDefText (&TemmaNoteTP, NULL);
+ IDDefSwitch (&RAmotorSw, NULL);
+ IDDefSwitch (&trackmodeSw, NULL);
+ IDDefText (&Port, NULL);
+ IDDefText (&TemmaVersion, NULL);
+ IDDefNumber (&Time, NULL);
+ IDDefNumber (&SDTime, NULL);
+ IDDefNumber (&cometNum, NULL);
+ IDDefNumber (&geoNum, NULL);
+}
+
+void ISNewBLOB (const char *dev, const char *name, int sizes[], char *blobs[], char *formats[], char *names[], int n)
+{
+ dev=dev;name=name;sizes=sizes;blobs=blobs;formats=formats;names=names;n=n;
+}
+
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n) {
+ /*IText *tp;*/
+
+ if (strcmp (dev, mydev))
+ return;
+
+ if (!strcmp (name, Port.name)) {
+ IUSaveText(PortT, texts[0]);
+ Port.s = IPS_OK;
+ IDSetText (&Port, NULL);
+ }
+ return;
+}
+
+/* client is sending us a new value for a Numeric vector property */
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n) {
+ /* ignore if not ours */
+ if (strcmp (dev, mydev))
+ return;
+
+ if (!strcmp (name, eqNum.name)) {
+ /* new equatorial target coords */
+ /*double newra = 0, newdec = 0;*/
+ int i, nset;
+
+ /* Check power, if it is off, then return */
+ if (power[0].s != ISS_ON)
+ {
+ eqNum.s = IPS_IDLE;
+ IDSetNumber(&eqNum, "Power is off");
+ return;
+ }
+
+ for (nset = i = 0; i < n; i++) {
+ /* Find numbers with the passed names in the eqNum property */
+ INumber *eqp = IUFindNumber (&eqNum, names[i]);
+
+ /* If the number found is Right ascension (eq[0]) then process it */
+ if (eqp == &eq[0])
+ {
+ currentRA = (values[i]);
+ nset += currentRA >= 0 && currentRA <= 24;
+ }
+ /* Otherwise, if the number found is Declination (eq[1]) then process it */
+ else if (eqp == &eq[1]) {
+ currentDec = (values[i]);
+ nset += currentDec >= -90 && currentDec <= 90;
+ }
+ } /* end for */
+
+ /* Did we process the two numbers? */
+ if (nset == 2) {
+ /*char r[32], d[32];*/
+
+ /* Set the mount state to BUSY */
+ eqNum.s = IPS_BUSY;
+
+ if (SLEWSW==ISS_ON || TRACKSW==ISS_ON){
+ IDSetNumber(&eqNum, "Moving to RA Dec %f %f", currentRA,
+ currentDec);
+ do_TemmaGOTO();
+ }
+
+ if (SYNCSW==ISS_ON){
+ IDSetNumber(&eqNum, "Syncing to RA Dec %f %f", currentRA, currentDec);
+ set_TemmaCurrentpos();
+ }
+ eqNum.s = IPS_OK;
+ IDSetNumber(&eqNum, "Synced");
+ }
+ /* We didn't process the two number correctly, report an error */
+ else {
+ /* Set property state to idle */
+ eqNum.s = IPS_IDLE;
+
+ IDSetNumber(&eqNum, "RA or Dec absent or bogus.");
+ }
+ return;
+ }
+}
+
+/* client is sending us a new value for a Switch property */
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ ISwitch *sp;
+
+ /* ignore if not ours */
+ if (strcmp (dev, mydev))
+ return;
+
+ if (!strcmp (name, powSw.name)) {
+ sp = IUFindSwitch (&powSw, names[0]);
+ if (!sp)
+ return;
+
+ fprintf(stderr,"new state %s\n",names[0]);
+
+ sp->s = states[0];
+ if (!strcmp(names[0],"CONNECT")) {
+ connectMount();
+ }
+ if (!strcmp(names[0],"DISCONNECT")) {
+ disconnectMount();
+ }
+ }
+
+ if (!strcmp (name, abortSlewSw.name)) {
+ if (POWSW){
+ TemmaabortSlew();
+ IDSetSwitch (&abortSlewSw, "Abort slew");
+ }
+ else {
+ IDSetSwitch (&abortSlewSw, "Power is off");
+ }
+ }
+
+ if (!strcmp (name, RAmotorSw.name)) {
+ if (POWSW){
+ sp = IUFindSwitch (&RAmotorSw, names[0]);
+ if (!sp)
+ return;
+
+ fprintf(stderr,"new state %s\n",names[0]);
+
+ sp->s = states[0];
+
+ RAmotorSw.s = IPS_BUSY;
+ if (!strcmp(names[0],"RUN")) {
+ set_TemmaStandbyState(0);
+ }
+
+ if (!strcmp(names[0],"STOP")) {
+ set_TemmaStandbyState(1);
+ }
+
+ if(get_TemmaStandbyState(buffer)){
+ RAmotorSw.s = IPS_IDLE;
+ IDSetSwitch (&RAmotorSw, "Error writing to port");
+ return;
+ }
+ }
+ else {
+ IDSetSwitch (&RAmotorSw, "Power is off");
+ }
+ }
+
+ if (!strcmp (name, OnCoordSetSw.name)) {
+ if (POWSW){
+ IUResetSwitches(&OnCoordSetSw);
+ sp = IUFindSwitch (&OnCoordSetSw, names[0]);
+ if (!sp)
+ return;
+
+ fprintf(stderr,"new state %s\n",names[0]);
+
+ sp->s = states[0];
+
+ IUResetSwitches(&OnCoordSetSw);
+ IUUpdateSwitches(&OnCoordSetSw, states, names, n);
+ /* currentSet = getOnSwitch(&OnCoordSetSw); */
+ OnCoordSetSw.s = IPS_OK;
+ IDSetSwitch(&OnCoordSetSw, NULL);
+ }
+ else {
+ IDSetSwitch (&OnCoordSetSw, "Power is off");
+ }
+ }
+}
+
+double calcLST(char *strlst){
+ time_t computertime;
+ struct tm gmt;
+ double jd, gmst;
+ double lst;
+ /*int a,b;*/
+
+ time(&computertime);
+ gmtime_r(&computertime, &gmt);
+ gmt.tm_mon+=1;
+ gmt.tm_year+=1900;
+ currentUTC=(double)gmt.tm_hour+(double)gmt.tm_min/60+(double)gmt.tm_sec/3600;
+
+ jd=UTtoJD(&gmt);
+ gmst=JDtoGMST(jd);
+
+ lst=(gmst-longitude)/15;
+
+ lst=(lst/24-(int)(lst/24))*24;
+
+ if(lst>=24)
+ lst-=24;
+ sprintf(strlst,"%.2d%.2d%.2d", (int)lst,
+ ((int)(lst*60))%60,
+ ((int)(lst*3600))%60);
+ currentLST=lst;
+ IDSetNumber (&SDTime, NULL);
+ IDSetNumber (&Time, NULL);
+
+ return 0;
+}
+
+#if 1
+/* update the mount over time */
+void readMountcurrentpos (void *p)
+{
+ char result[32];
+
+ if(POWSW){
+ get_TemmaCurrentpos(result);
+ calcLST(result);
+
+ /* This is a temporary workaround to allow
+ clients with only one eq property to work */
+ currentRA=temmaRA;
+ currentDec=temmaDec;
+
+ /* again */
+ IEAddTimer (POLLMS, readMountcurrentpos, NULL);
+ }
+}
+#endif
+
+static void connectMount () {
+ fprintf(stderr,"opening mount port %s\n",PortT->text);
+ if (power[0].s == ISS_ON){
+ if (Port.s != IPS_OK){
+ powSw.s = IPS_IDLE;
+ power[0].s = ISS_OFF;
+
+ IDSetSwitch (&powSw, "Port not set.");
+ return;
+ }
+ else {
+ if (TemmaConnect(PortT->text)==0){
+ IDSetText (&Port, "Port is opened.");
+ if( !get_TemmaVERSION(buffer)){
+ powSw.s = IPS_OK;
+ power[0].s = ISS_ON;
+ power[1].s = ISS_OFF;
+ snprintf(buffer2,sizeof( buffer2 ),"%s",buffer+4);
+
+ IDSetText(&TemmaVersion , "Temma version set");
+ TemmaVersionT->text = realloc(TemmaVersionT->text, strlen(buffer2)+1);
+ if (!TemmaVersionT->text){
+ fprintf(stderr,"Memory allocation error");
+ return;
+ }
+ IDSetSwitch (&powSw, "Mount is ready");
+ IDSetSwitch (&powSw, VERSION);
+
+ strcpy(TemmaVersionT->text, buffer2);
+ TemmaVersion.s = IPS_OK;
+ IDSetText (&TemmaVersion, NULL);
+ IDLog("%s", buffer2);
+ /* start timer to read mount coords */
+ IEAddTimer (POLLMS, readMountcurrentpos, NULL);
+ }
+ else {
+ powSw.s = IPS_IDLE;
+ power[0].s = ISS_OFF;
+ power[1].s = ISS_ON;
+ IDSetText(&Port , "Com error");
+ IDSetSwitch (&powSw, "Port not set.");
+ }
+
+ if(get_TemmaStandbyState(answer)){
+ IDSetSwitch (&RAmotorSw, "Error writing to port");
+ return;
+ }
+ }
+ else {
+ powSw.s = IPS_IDLE;
+ power[0].s = ISS_OFF;
+ power[1].s = ISS_ON;
+
+ IDSetSwitch (&powSw, "Failed to open port.");
+ }
+ }
+ }
+}
+
+static void disconnectMount () {
+ fprintf(stderr,"closing mount port %s\n",PortT->text);
+ if (power[1].s == ISS_ON){
+ if (Port.s != IPS_OK){
+ powSw.s = IPS_IDLE;
+ power[0].s = ISS_OFF;
+
+ IDSetSwitch (&powSw, "Port not set.");
+ return;
+ }
+ else {
+ TemmaDisconnect();
+ powSw.s = IPS_IDLE;
+ power[0].s = ISS_OFF;
+
+ IDSetSwitch (&powSw, "Port is closed.");
+ }
+ }
+ else {
+ fprintf(stderr, "Already disconnected \n");
+ }
+}
+
+int TemmaConnect(const char *device) {
+ fprintf(stderr, "Connecting to device %s\n", device);
+
+ if (openPort(device) < 0){
+ fprintf(stderr, "Error connecting to device %s\n", device);
+ return -1;
+ }
+ else{
+ return 0;
+ }
+}
+
+int TemmaDisconnect() {
+ fprintf(stderr, "Disconnected.\n");
+ close(fd);
+
+ return 0;
+}
+
+int set_CometTracking(int RArate, int DECrate){
+#if 0
+ Set Comet Tracking
+ LM+/-99999,+/-9999
+ RA : Adjust Sidereal time by seconds per Day
+
+ DEC : Adjust DEC tracking by Minutes Per Day
+ valeur DEC min=-600 /max=+600 (+/-10 deg / jour)
+
+ Example:
+ LM+120,+30 would slow the RA speed by 86164/86284 and
+ the Dec would track at 30 Minutes a day.
+ To stop tracking either send a LM0,0 (or a PS
+ sauf erreur on constate en faite l inverse en RA
+ retour Vsideral => LM0,0 ou LM+0,+0
+#endif
+ char local_buffer[16];
+
+ if (RArate<-21541){
+ RArate=-21541;
+ }
+
+ if (RArate>21541){
+ RArate=21541;
+ }
+
+ if (DECrate<-600){
+ DECrate=-600;
+ }
+
+ if (DECrate>600){
+ DECrate=600;
+ }
+
+ snprintf(local_buffer, sizeof( local_buffer ), "%+6d,%+5d", RArate, DECrate);
+ set_TemmaCometTracking(local_buffer);
+
+ return 0;
+}
+
+int TemmaabortSlew() {
+ if (portWrite("PS") < 0)
+ return -1;
+
+ return 0;
+}
+
+int do_TemmaGOTO() {
+ /* Temma Sync */
+ char command[16];
+ char sign;
+ double dec;
+
+ calcLST(buffer);
+ set_TemmaLST(buffer);
+
+ dec=fabs(currentDec);
+ if (currentDec>0){
+ sign='+';
+ }
+ else {
+ sign='-';
+ }
+
+ snprintf(buffer, sizeof(buffer),"%.2d%.2d%.2d%c%.2d%.2d%.1d",
+ (int)currentRA,(int)(currentRA*(double)60)%60,((int)(currentRA*(double)6000))%100,sign,
+ (int)dec,(int)(dec*(double)60)%60,((int)(dec*(double)600))%10);
+ fprintf(stderr,"Goto %s\n", buffer);
+
+ snprintf(command,14,"P%s",buffer);
+ buffer[14]=0;
+ fprintf(stderr,"Goto command:%s\n", command);
+ portWrite(command);
+
+ portRead(buffer,-1,TEMMA_TIMEOUT);
+ if(command[0]=='R'){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int extractRA(char *buf){
+ int r,h,m,s;
+ /*double dra;*/
+
+ r=atoi(buf);
+ h=r/10000;
+ m=r/100-100*h;
+ s=(r%100)*.6;
+ temmaRA=((double)h+((double)m + (double)s/60)/60);
+ IDSetNumber (&eqTemma, NULL);
+ /* fprintf(stderr,"extractRA: %s %d %d %d %d %lf\n",buf,r,h,m,s,dra);*/
+ return 0;
+}
+
+int extractDEC(char *buf){
+ int dec,d,m,s;
+ /*double ddec;*/
+
+ dec=atoi(buf+1);
+ d=dec/1000;
+ m=dec/10-100*d;
+ s=(dec%10)*6;
+ temmaDec=((double)d+((double)m + (double)s/60)/60);
+ if (*buf=='-')
+ temmaDec*=-1;
+
+ IDSetNumber (&eqTemma, NULL);
+
+
+ /* fprintf(stderr,"extractDEC: %s %d %d %d %d %lf\n",buf,dec,d,m,s,ddec);*/
+ return 0;
+}
+
+
+int get_TemmaCurrentpos(char *local_buffer){
+ char buf[16];
+
+ if (portWrite("E") < 0)
+ return -1;
+
+ if(portRead(local_buffer,-1,TEMMA_TIMEOUT)==SUCCESS){
+ if(strstr(local_buffer, "E")==local_buffer){
+ strncpy(buf,local_buffer+1,6);
+ buf[6]=0;
+ extractRA(buf);
+
+ strncpy(buf,local_buffer+7,6);
+ buf[6]=0;
+ extractDEC(buf);
+ return 0;
+ }
+ else {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int set_TemmaCurrentpos(void) {
+ /* Temma Sync */
+ char buf[16], sign;
+ double dec;
+
+ calcLST(buf);
+ set_TemmaLST(buf);
+ portWrite("Z");
+ calcLST(buf);
+ set_TemmaLST(buf);
+
+ dec=fabs(currentDec);
+ if (currentDec>0){
+ sign='+';
+ }
+ else {
+ sign='-';
+ }
+
+ sprintf(buffer,"%.2d%.2d%.2d%c%.2d%.2d%.1d",
+ (int)currentRA,(int)(currentRA*(double)60)%60,((int)(currentRA*(double)6000))%100,sign,
+ (int)dec,(int)(dec*(double)60)%60,((int)(dec*(double)600))%10);
+ fprintf(stderr,"sync to %s %f %f\n", buffer,currentRA,dec);
+
+ snprintf(buf, sizeof(buf), "D%s",buffer);
+ buf[13]=0;
+ portWrite(buf);
+ *buffer=0;
+
+ portRead(buffer,-1,TEMMA_TIMEOUT);
+ if(buffer[0]=='R'){
+ return 0;
+ }
+ else{
+ return -1;
+ }
+}
+
+int do_TemmaSLEW(char mode){
+ /*char command[16];*/
+
+ sprintf(buffer,"M%c",mode); /* see bit definition in Temmadriver.h */
+
+ if (portWrite(buffer) < 0)
+ return -1;
+
+ return 0;
+}
+
+int get_TemmaVERSION(char *local_buffer){
+ int err;
+
+ if ((err=portWrite("v")) < 0){
+ return err;
+ }
+
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(strstr(local_buffer, "ver")==local_buffer){
+ return 0;
+ }
+ else
+ return EREAD;
+}
+
+int get_TemmaGOTOstatus(char *local_buffer){
+ /*
+ 0 no ongoing goto
+ 1 ongoing Goto
+ -1 error
+ */
+ if (portWrite("s") < 0)
+ return -1;
+
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(strstr(local_buffer, "s")==local_buffer){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int get_TemmaBOTHcorrspeed(char *local_buffer){
+ if (portWrite("lg") < 0)
+ return -1;
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(strstr(local_buffer, "lg")==local_buffer){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int get_TemmaDECcorrspeed(char *local_buffer){
+ if (portWrite("lb") < 0)
+ return -1;
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(strstr(local_buffer, "lb")==local_buffer){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int set_TemmaDECcorrspeed(char *local_buffer){
+ char command[16];
+
+ snprintf(command, 4, "LB%s",local_buffer);
+
+ if (portWrite(command) < 0)
+ return -1;
+ return 0;
+}
+
+int get_TemmaRAcorrspeed(char *local_buffer){
+ if (portWrite("la") < 0)
+ return -1;
+
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(strstr(local_buffer, "la")==local_buffer){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int set_TemmaRAcorrspeed(char *local_buffer){
+ char command[16];
+
+ snprintf(command, 4,"LA%s",local_buffer);
+
+ if (portWrite(command) < 0)
+ return -1;
+ return 0;
+}
+
+int get_TemmaLatitude(char *local_buffer){
+ if (portWrite("i") < 0)
+ return -1;
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(local_buffer[0]=='i'){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int set_TemmaLatitude(char *local_buffer){
+ char command[16];
+ double lat;
+ char sign;
+
+ lat=fabs(latitude);
+ if (latitude>0){
+ sign='+';
+ }
+ else {
+ sign='-';
+ }
+
+ sprintf(command,"I%c%.2d%.2d%.1d", sign,
+ (int)lat,
+ (int)(lat*(double)60)%60,
+ ((int)(lat*(double)600))%10);
+
+ if (portWrite(command) < 0)
+ return -1;
+ return 0;
+}
+
+int get_TemmaLST(char *local_buffer){
+ if (portWrite("g") < 0)
+ return -1;
+
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(local_buffer[0]=='g'){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+
+int set_TemmaLST(char *local_buffer){
+ char command[16];
+ snprintf(command,7,"T%s",local_buffer);
+
+ if (portWrite(command) < 0)
+ return -1;
+ return 0;
+}
+
+
+int get_TemmaCometTracking(char *local_buffer){
+ if (portWrite("lm") < 0)
+ return -1;
+ portRead(local_buffer,-1,TEMMA_TIMEOUT);
+ if(strstr(local_buffer, "lm")==local_buffer){
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int set_TemmaStandbyState(int on){
+ if (on){
+ return portWrite("STN-ON");
+ }
+ else{
+ return portWrite("STN-OFF");
+ }
+ return 0;
+}
+
+int get_TemmaStandbyState(unsigned char *local_buffer){
+ int nb;
+ int status;
+
+ if ((nb=portWrite("STN-COD")) < 0){
+ IDSetSwitch (&RAmotorSw, "I/O error when asking RAmotor status");
+ return -1;
+ }
+
+ if((status=portRead(local_buffer,-1,TEMMA_TIMEOUT)==SUCCESS)){
+ if(strstr(local_buffer, "stn")==local_buffer){
+ local_buffer[7]=0;
+ if (strstr(local_buffer,"on")){ /* stanby on */
+ RAmotorSw.s = IPS_OK;
+ RAmotor[0].s = ISS_OFF;
+ RAmotor[1].s = ISS_ON;
+ IDSetSwitch (&RAmotorSw, "RA motor is off.");
+ }
+ else{
+ if (strstr(local_buffer,"off")){ /* stanby off */
+ RAmotorSw.s = IPS_OK;
+ RAmotor[0].s = ISS_ON;
+ RAmotor[1].s = ISS_OFF;
+ IDSetSwitch (&RAmotorSw, "RA motor is on.");
+ }
+ else {
+ RAmotorSw.s = IPS_OK;
+ IDSetSwitch (&RAmotorSw, "I/O error when getting RAmotor status");
+ }
+ }
+ }
+ return 0;
+ }
+ if (status<=ETIMEOUT && status >=ECOMMAND){
+ IDSetSwitch(&RAmotorSw, "%s", errormes[ETIMEOUT - status]);
+ }
+
+ return -1;
+}
+
+int set_TemmaCometTracking(char *local_buffer){
+ char command[16];
+
+ snprintf(command,15,"LM%s",local_buffer);
+ if (portWrite(command) < 0)
+ return -1;
+ return 0;
+}
+
+int set_TemmaSolarRate(void){
+ if (portWrite("LK") < 0)
+ return -1;
+ return 0;
+}
+
+int set_TemmaStellarRate(void){
+ if (portWrite("LL") < 0)
+ return -1;
+ return 0;
+}
+
+
+int switch_Temmamountside(void){
+ if (portWrite("PT") < 0)
+ return -1;
+ return 0;
+}
+
+/**********************************************************************
+ * Comm
+ **********************************************************************/
+
+int openPort(const char *portID) {
+ struct termios ttyOptions;
+
+ if ( (fd = open(portID, O_RDWR)) == -1)
+ return -1;
+ memset(&ttyOptions, 0, sizeof(ttyOptions));
+ tcgetattr(fd, &ttyOptions);
+
+ /* 8 bit, enable read */
+ ttyOptions.c_cflag |= CS8;
+ /* parity */
+ ttyOptions.c_cflag |= PARENB;
+ ttyOptions.c_cflag &= ~PARODD;
+ ttyOptions.c_cflag &= ~CSTOPB;
+ ttyOptions.c_cflag |= CRTSCTS;
+
+ /* set baud rate */
+ cfsetispeed(&ttyOptions, B19200);
+ cfsetospeed(&ttyOptions, B19200);
+
+ /* set input/output flags */
+ ttyOptions.c_iflag = IGNBRK;
+
+ /* Read at least one byte */
+ ttyOptions.c_cc[VMIN] = 1;
+ ttyOptions.c_cc[VTIME] = 5;
+
+ /* Misc. */
+ ttyOptions.c_lflag = 0;
+ ttyOptions.c_oflag = 0;
+
+ /* set attributes */
+ tcsetattr(fd, TCSANOW, &ttyOptions);
+
+ /* flush the channel */
+ tcflush(fd, TCIOFLUSH);
+ return (fd);
+}
+
+int portWrite(char * buf) {
+ int nbytes=strlen(buf); /*, totalBytesWritten;*/
+ int bytesWritten = 0;
+ /*int retry=10;*/
+
+ bytesWritten = write(fd, buf, nbytes);
+ bytesWritten += write(fd, "\r\n", 2);
+ /*fprintf(stderr,"portwrite :%d octets %s\n", bytesWritten, buf);*/
+
+ if (bytesWritten!=nbytes+2){
+ perror("write error: ");
+ IDLog("Error writing to port");
+ return EWRITE;
+ }
+ return (bytesWritten);
+}
+
+int portRead(char *buf, int nbytes, int timeout) {
+ /*
+ A very basic finite state machine monitors
+ the bytes read ;
+ state 0 : read regular bytes
+ state 1 : just read a \n, waiting for a \r
+ state 2 : read a \n and a \r, command is over.
+
+ Not sure it is useful here but I use a more
+ sophisticated version of this with a GPS receiver
+ and it is robust and reliable
+
+ We return a null terminated string.
+ */
+
+ int bytesRead = 0, state=0, /*i=0,*/ current=0;
+ /*int totalBytesRead = 0;*/
+ int err;
+
+ if ( (err = TemmareadOut(timeout)) ){
+ switch (err){
+ case ETIMEOUT:
+ IDLog("Error: timeout while reading");
+ return err;
+ }
+ }
+
+ while (read(fd,buf+bytesRead,1)==1){
+ /* fprintf(stderr,"%c",buf[bytesRead]); */
+ fflush(NULL);
+ switch (state) {
+ case 0:
+ if(buf[bytesRead]==13)
+ state=1;
+ break;
+
+ case 1:
+ if(buf[bytesRead]==10)
+ state=2;
+ else
+ if(buf[bytesRead]==13)
+ state=1;
+ else
+ state=0;
+ break;
+ }
+
+ ++current;
+
+ if (state==2){
+ /*process(buf);*/
+ buf[bytesRead+1]=0;
+ state=current=0;
+ return SUCCESS;
+ }
+
+ bytesRead=current;
+ }
+ return state;
+}
+
+int TemmareadOut(int timeout) {
+ struct timeval tv;
+ fd_set readout;
+ int retval;
+
+ FD_ZERO(&readout);
+ FD_SET(fd, &readout);
+
+ /* wait for 'timeout' seconds */
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ /* Wait till we have a change in the fd status */
+ retval = select (fd+1, &readout, NULL, NULL, &tv);
+
+ /* Return 0 on successful fd change */
+ if (retval > 0)
+ return 0;
+ /* Return -1 due to an error */
+ else if (retval == EREAD)
+ return retval;
+ /* Return -2 if time expires before anything interesting happens */
+ else {
+ return ETIMEOUT;
+ }
+}
+
diff --git a/kstars/kstars/indi/temmadriver.h b/kstars/kstars/indi/temmadriver.h
new file mode 100644
index 00000000..79926c3f
--- /dev/null
+++ b/kstars/kstars/indi/temmadriver.h
@@ -0,0 +1,252 @@
+/*
+ Temma INDI driver
+ Copyright (C) 2004 Francois Meyer (dulle @ free.fr)
+ Remi Petitdemange for the temma protocol
+ Reference site is http://dulle.free.fr/alidade/indi.php
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ */
+
+#ifndef TEMMADRIVER_H
+#define TEMMADRIVER_H
+#define VERSION "Temma indi driver Ver 0.0, fm-2004/10/09"
+#if 0
+bit definition for M message : slew speed and parameters
+#endif
+#define HS 0x01 /* high speed */
+#define RR 0x02 /* RA right */
+#define RL 0x04 /* RA left */
+#define DU 0x08 /* DEC up */
+#define DD 0x10 /* DEC down */
+#define EN 0x20 /* ENC on */
+#define BB 0x40 /* Allways set */
+#if 0
+(HS|RR|EN|BB)
+#endif
+#define HRAD (M_PI/12)
+#define DEGRAD (M_PI/180)
+#define TEMMA_TIMEOUT 1 /* FD timeout in seconds */
+
+ /* error codes */
+#define SUCCESS (2) /* return value for successful read */
+#define ETIMEOUT (-2) /* timeout */
+#define EREAD (-3) /* error reading from port */
+#define EWRITE (-4) /* error writing to port */
+#define ECOMMAND (-5) /* unexpected answer */
+ /* Definitions */
+
+#define mydev "Temma" /* Device name */
+#define MAIN_GROUP "Main Control" /* Group name */
+#define COMM_GROUP "Communication" /* Group name */
+#define MOVE_GROUP "Movement Control"
+#define DATETIME_GROUP "Date/Time/Location"
+
+#define SLEWSW OnCoordSetS[0].s
+#define SYNCSW OnCoordSetS[1].s
+#define TRACKSW OnCoordSetS[2].s
+#define POWSW (power[0].s==ISS_ON)
+
+#define SLEWRATE 1 /* slew rate, degrees/s */
+#define POLLMS 1000 /* poll period, ms */
+
+#define latitude geo[0].value /* scope's current rads. */
+#define longitude geo[1].value /* scope's current rads. */
+#define currentUTC UTC[0].value /* scope's current rads. */
+#define currentLST STime[0].value /* scope's current rads. */
+#define currentRA eq[0].value /* scope's current RA, rads. */
+#define currentDec eq[1].value /* scope's current Dec, rads. */
+#define temmaRA eqtem[0].value /* scope's current RA, rads. */
+#define temmaDec eqtem[1].value /* scope's current Dec, rads. */
+
+
+int openPort(const char *portID);
+int portRead(char *buf, int nbytes, int timeout);
+int portWrite(char * buf);
+int TemmareadOut(int timeout);
+static void mountInit(void);
+void ISGetProperties (const char *dev);
+void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+double calcLST(char *strlst);
+int TemmaConnect(const char *device) ;
+int TemmaDisconnect(void) ;
+int set_CometTracking(int RArate, int DECrate);
+int TemmaabortSlew(void) ;
+int do_TemmaGOTO(void) ;
+int extractRA(char *buf);
+int extractDEC(char *buf);
+int get_TemmaCurrentpos(char *buffer);
+int set_TemmaCurrentpos(void) ;
+int do_TemmaSLEW(char mode);
+int get_TemmaVERSION(char *buffer);
+int get_TemmaGOTOstatus(char *buffer);
+int get_TemmaBOTHcorrspeed(char *buffer);
+int get_TemmaDECcorrspeed(char *buffer);
+int set_TemmaDECcorrspeed(char *buffer);
+int get_TemmaRAcorrspeed(char *buffer);
+int set_TemmaRAcorrspeed(char *buffer);
+int get_TemmaLatitude(char *buffer);
+int set_TemmaLatitude(char *buffer);
+int get_TemmaLST(char *buffer);
+int set_TemmaLST(char *buffer);
+int set_TemmaStandbyState(int on);
+int get_TemmaStandbyState(unsigned char *buffer);
+int get_TemmaCometTracking(char *buffer);
+int set_TemmaCometTracking(char *buffer);
+int set_TemmaSolarRate(void);
+int set_TemmaStellarRate(void);
+int switch_Temmamountside(void);
+
+static void disconnectMount (void);
+static void connectMount (void);
+static void readMountcurrentpos (void *);
+
+/***************************/
+/* RA motor control switch */
+/***************************/
+static ISwitch RAmotor[] = {
+ {"RUN", "On", ISS_OFF, 0, 0},
+ {"STOP", "Off", ISS_ON, 0, 0} };
+
+static ISwitchVectorProperty RAmotorSw = {
+ mydev, "RA motor", "RA motor", MOVE_GROUP, IP_RW, ISR_ATMOST1,
+ 0, IPS_IDLE, RAmotor, NARRAY(RAmotor), "", 0};
+
+/*****************************/
+/* Track mode control switch */
+/*****************************/
+static ISwitch trackmode[] = {
+ {"Sidereal", "Sidereal", ISS_ON, 0, 0},
+ {"Lunar", "Lunar", ISS_OFF, 0, 0},
+ {"Comet", "Comet", ISS_OFF, 0, 0}, };
+
+static ISwitchVectorProperty trackmodeSw = {
+ mydev, "Tracking mode", "Tracking mode", MOVE_GROUP, IP_RW, ISR_1OFMANY,
+ 0, IPS_IDLE, trackmode, NARRAY(trackmode), "", 0};
+
+/*****************************/
+/* Power control switch */
+/*****************************/
+static ISwitch power[] = {
+ {"CONNECT", "On", ISS_OFF, 0, 0}, {"DISCONNECT", "Off", ISS_ON, 0, 0}, };
+
+static ISwitchVectorProperty powSw = {
+ mydev, "CONNECTION", "Connection", MAIN_GROUP, IP_RW, ISR_ATMOST1,
+ 0, IPS_IDLE, power, NARRAY(power), "", 0};
+
+/*******************************/
+/* Temma version text property */
+/*******************************/
+static IText TemmaVersionT[] = {{"VERSION", "Version", 0, 0, 0, 0}};
+static ITextVectorProperty TemmaVersion = {
+ mydev, "VERSION", "Temma version", COMM_GROUP, IP_RO, 0,
+ IPS_OK, TemmaVersionT, NARRAY(TemmaVersionT), "", 0};
+
+
+/*******************************/
+/* Driver notes text property */
+/*******************************/
+static IText TemmaNoteT[] = {{"Note", "", 0, 0, 0, 0}, {"Feedback", "", 0, 0,0 ,0}};
+static ITextVectorProperty TemmaNoteTP = { mydev, "Temma Driver", "", MAIN_GROUP, IP_RO, 0, IPS_OK, TemmaNoteT, NARRAY(TemmaNoteT), "", 0};
+
+/*******************************/
+/* Port names text property */
+/*******************************/
+static IText PortT[] = {{"PORT", "Port", 0, 0, 0, 0}};
+static ITextVectorProperty Port = {
+ mydev, "DEVICE_PORT", "Ports", COMM_GROUP,
+ IP_RW, 0, IPS_OK, PortT, NARRAY(PortT), "", 0};
+
+/*******************************/
+/* EQUATORIAL_COORD RW property */
+/*******************************/
+static INumber eq[] = {
+ {"RA" ,"RA H:M:S" , "%10.6m", 0, 24, 0, 0, 0, 0, 0},
+ {"DEC", "Dec D:M:S", "%10.6m", -90, 90, 0, 0, 0, 0, 0}
+};
+static INumberVectorProperty eqNum = {
+ mydev, "EQUATORIAL_EOD_COORD", "Equatorial JNow",
+ MAIN_GROUP , IP_RW, 0, IPS_IDLE, eq, NARRAY(eq), "", 0};
+
+/*******************************/
+/* MOUNT_COORD RO property */
+/*******************************/
+static INumber eqtem[] = {
+ {"RA", "RA H:M:S", "%10.6m", 0, 24, 0, 0, 0, 0, 0},
+ {"DEC", "Dec D:M:S", "%10.6m", -90, 90, 0, 0, 0, 0, 0}
+};
+static INumberVectorProperty eqTemma = {
+ mydev, "Temma", "Mount coordinates",
+ MAIN_GROUP , IP_RO, 0, IPS_IDLE, eqtem, NARRAY(eqtem), "", 0};
+
+
+/* Traccking correction parameters (i.e. to track comets) */
+static INumber comet[] = {
+ {"RAcorrspeed","Comet RA motion arcmin/day","%+5d",-21541,21541,0,0,0,0,0},
+ {"DECcor rspeed", "Comet DEC motion arcmin/day", "%+4d", -600, 600,0, 0., 0, 0, 0}
+};
+
+static INumberVectorProperty cometNum = {
+ mydev, "COMET_TRACKING", "Comet tracking parameters",
+ MOVE_GROUP, IP_RW, 0, IPS_IDLE, comet, NARRAY(comet), "", 0};
+
+/* Date & Time */
+static INumber UTC[] = {
+ {"UTC", "UTC", "%10.6m" , 0.,0.,0.,0., 0, 0, 0}};
+INumberVectorProperty Time = {
+ mydev, "TIME", "UTC Time", DATETIME_GROUP,
+ IP_RW, 0, IPS_IDLE, UTC, NARRAY(UTC), "", 0};
+
+static INumber STime[] = {
+ {"LST", "Sidereal time", "%10.6m" ,
+ 0.,0.,0.,0., 0, 0, 0}};
+
+INumberVectorProperty SDTime = {
+ mydev, "SDTIME", "Sidereal Time",
+ DATETIME_GROUP, IP_RW, 0, IPS_IDLE,
+ STime, NARRAY(STime), "", 0};
+
+static ISwitch OnCoordSetS[] = {
+ {"SLEW", "Goto", ISS_OFF, 0, 0 },
+ {"SYNC", "Sync", ISS_ON, 0 , 0},
+ {"TRACK", "Track", ISS_OFF, 0, 0 }};
+
+static ISwitchVectorProperty OnCoordSetSw = {
+ mydev, "ON_COORD_SET", "On Set",
+ MAIN_GROUP, IP_RW, ISR_1OFMANY, 0,
+ IPS_IDLE, OnCoordSetS, NARRAY(OnCoordSetS), "", 0};
+
+
+
+static ISwitch abortSlewS[] = {
+ {"ABORT", "Abort", ISS_OFF, 0, 0 }};
+static ISwitchVectorProperty abortSlewSw = {
+ mydev, "ABORT_MOTION", "******* ABORT GOTO *********",
+ MAIN_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE,
+ abortSlewS, NARRAY(abortSlewS), "", 0};
+
+/* geographic location */
+static INumber geo[] = {
+ {"LAT", "Lat. D:M:S +N", "%10.6m", -90., 90., 0., 0., 0, 0, 0},
+ {"LONG", "Long. D:M:S +E", "%10.6m", 0., 360., 0., 0., 0, 0, 0} };
+
+static INumberVectorProperty geoNum = {
+ mydev, "GEOGRAPHIC_COORD", "Geographic Location",
+ DATETIME_GROUP, IP_RW, 0., IPS_IDLE,
+ geo, NARRAY(geo), "", 0};
+
+#endif
diff --git a/kstars/kstars/indi/v4ldriver.cpp b/kstars/kstars/indi/v4ldriver.cpp
new file mode 100644
index 00000000..edb4b30a
--- /dev/null
+++ b/kstars/kstars/indi/v4ldriver.cpp
@@ -0,0 +1,875 @@
+#if 0
+ V4L INDI Driver
+ INDI Interface for V4L devices
+ Copyright (C) 2003-2005 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#include "v4ldriver.h"
+
+V4L_Driver::V4L_Driver()
+{
+ V4LFrame = (img_t *) malloc (sizeof(img_t));
+
+ if (V4LFrame == NULL)
+ {
+ IDMessage(NULL, "Error: unable to initialize driver. Low memory.");
+ IDLog("Error: unable to initialize driver. Low memory.");
+ return;
+ }
+
+ camNameT[0].text = NULL;
+ PortT[0].text = NULL;
+ IUSaveText(&PortT[0], "/dev/video0");
+
+ divider = 128.;
+
+
+}
+
+V4L_Driver::~V4L_Driver()
+{
+ free (V4LFrame);
+}
+
+
+void V4L_Driver::initProperties(const char *dev)
+{
+
+ strncpy(device_name, dev, MAXINDIDEVICE);
+
+ /* Connection */
+ fillSwitch(&PowerS[0], "CONNECT", "Connect", ISS_OFF);
+ fillSwitch(&PowerS[1], "DISCONNECT", "Disconnect", ISS_ON);
+ fillSwitchVector(&PowerSP, PowerS, NARRAY(PowerS), dev, "CONNECTION", "Connection", COMM_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
+
+ /* Port */
+ fillText(&PortT[0], "PORT", "Port", "/dev/ttyS0");
+ fillTextVector(&PortTP, PortT, NARRAY(PortT), dev, "DEVICE_PORT", "Ports", COMM_GROUP, IP_RW, 0, IPS_IDLE);
+
+ /* Video Stream */
+ fillSwitch(&StreamS[0], "ON", "", ISS_OFF);
+ fillSwitch(&StreamS[1], "OFF", "", ISS_ON);
+ fillSwitchVector(&StreamSP, StreamS, NARRAY(StreamS), dev, "VIDEO_STREAM", "Video Stream", COMM_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ /* Compression */
+ fillSwitch(&CompressS[0], "ON", "", ISS_ON);
+ fillSwitch(&CompressS[1], "OFF", "", ISS_OFF);
+ fillSwitchVector(&CompressSP, CompressS, NARRAY(StreamS), dev, "Compression", "", IMAGE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ /* Image type */
+ fillSwitch(&ImageTypeS[0], "Grey", "", ISS_ON);
+ fillSwitch(&ImageTypeS[1], "Color", "", ISS_OFF);
+ fillSwitchVector(&ImageTypeSP, ImageTypeS, NARRAY(ImageTypeS), dev, "Image Type", "", IMAGE_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ /* Camera Name */
+ fillText(&camNameT[0], "Model", "", "");
+ fillTextVector(&camNameTP, camNameT, NARRAY(camNameT), dev, "Camera Model", "", COMM_GROUP, IP_RO, 0, IPS_IDLE);
+
+ /* Expose */
+ fillNumber(&ExposeTimeN[0], "EXPOSE_DURATION", "Duration (s)", "%5.2f", 0., 36000., 0.5, 1.);
+ fillNumberVector(&ExposeTimeNP, ExposeTimeN, NARRAY(ExposeTimeN), dev, "CCD_EXPOSE_DURATION", "Expose", COMM_GROUP, IP_RW, 60, IPS_IDLE);
+
+/* Frame Rate */
+ fillNumber(&FrameRateN[0], "RATE", "Rate", "%0.f", 1., 50., 1., 10.);
+ fillNumberVector(&FrameRateNP, FrameRateN, NARRAY(FrameRateN), dev, "FRAME_RATE", "Frame Rate", COMM_GROUP, IP_RW, 60, IPS_IDLE);
+
+ /* Frame dimension */
+ fillNumber(&FrameN[0], "X", "X", "%.0f", 0., 0., 0., 0.);
+ fillNumber(&FrameN[1], "Y", "Y", "%.0f", 0., 0., 0., 0.);
+ fillNumber(&FrameN[2], "WIDTH", "Width", "%.0f", 0., 0., 10., 0.);
+ fillNumber(&FrameN[3], "HEIGHT", "Height", "%.0f", 0., 0., 10., 0.);
+ fillNumberVector(&FrameNP, FrameN, NARRAY(FrameN), dev, "CCD_FRAME", "Frame", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
+
+ /*fillNumber(&ImageSizeN[0], "WIDTH", "Width", "%0.f", 0., 0., 10., 0.);
+ fillNumber(&ImageSizeN[1], "HEIGHT", "Height", "%0.f", 0., 0., 10., 0.);
+ fillNumberVector(&ImageSizeNP, ImageSizeN, NARRAY(ImageSizeN), dev, "IMAGE_SIZE", "Image Size", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);*/
+
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ fillNumber(&ImageAdjustN[0], "Contrast", "", "%0.f", 0., 256., 1., 0.);
+ fillNumber(&ImageAdjustN[1], "Brightness", "", "%0.f", 0., 256., 1., 0.);
+ fillNumber(&ImageAdjustN[2], "Hue", "", "%0.f", 0., 256., 1., 0.);
+ fillNumber(&ImageAdjustN[3], "Color", "", "%0.f", 0., 256., 1., 0.);
+ fillNumber(&ImageAdjustN[4], "Whiteness", "", "%0.f", 0., 256., 1., 0.);
+ fillNumberVector(&ImageAdjustNP, ImageAdjustN, NARRAY(ImageAdjustN), dev, "Image Adjustments", "", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
+ #else
+ fillNumberVector(&ImageAdjustNP, NULL, 0, dev, "Image Adjustments", "", IMAGE_GROUP, IP_RW, 60, IPS_IDLE);
+ #endif
+
+ // We need to setup the BLOB (Binary Large Object) below. Using this property, we can send FITS to our client
+ strcpy(imageB.name, "CCD1");
+ strcpy(imageB.label, "Feed");
+ strcpy(imageB.format, "");
+ imageB.blob = 0;
+ imageB.bloblen = 0;
+ imageB.size = 0;
+ imageB.bvp = 0;
+ imageB.aux0 = 0;
+ imageB.aux1 = 0;
+ imageB.aux2 = 0;
+
+ strcpy(imageBP.device, dev);
+ strcpy(imageBP.name, "Video");
+ strcpy(imageBP.label, "Video");
+ strcpy(imageBP.group, COMM_GROUP);
+ strcpy(imageBP.timestamp, "");
+ imageBP.p = IP_RO;
+ imageBP.timeout = 0;
+ imageBP.s = IPS_IDLE;
+ imageBP.bp = &imageB;
+ imageBP.nbp = 1;
+ imageBP.aux = 0;
+
+}
+
+void V4L_Driver::initCamBase()
+{
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ v4l_base = new V4L1_Base();
+ #else
+ v4l_base = new V4L2_Base();
+ #endif
+}
+
+void V4L_Driver::ISGetProperties (const char *dev)
+{
+
+ if (dev && strcmp (device_name, dev))
+ return;
+
+ /* COMM_GROUP */
+ IDDefSwitch(&PowerSP, NULL);
+ IDDefText(&PortTP, NULL);
+ IDDefText(&camNameTP, NULL);
+ IDDefSwitch(&StreamSP, NULL);
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ IDDefNumber(&FrameRateNP, NULL);
+ #endif
+ IDDefNumber(&ExposeTimeNP, NULL);
+ IDDefBLOB(&imageBP, NULL);
+
+ /* Image properties */
+ IDDefSwitch(&CompressSP, NULL);
+ IDDefSwitch(&ImageTypeSP, NULL);
+ IDDefNumber(&FrameNP, NULL);
+
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ IDDefNumber(&ImageAdjustNP, NULL);
+ #endif
+
+
+
+}
+
+void V4L_Driver::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ char errmsg[ERRMSGSIZ];
+
+ /* ignore if not ours */
+ if (dev && strcmp (device_name, dev))
+ return;
+
+ /* Connection */
+ if (!strcmp (name, PowerSP.name))
+ {
+ IUResetSwitches(&PowerSP);
+ IUUpdateSwitches(&PowerSP, states, names, n);
+ connectCamera();
+ return;
+ }
+
+ /* Compression */
+ if (!strcmp(name, CompressSP.name))
+ {
+ IUResetSwitches(&CompressSP);
+ IUUpdateSwitches(&CompressSP, states, names, n);
+ CompressSP.s = IPS_OK;
+
+ IDSetSwitch(&CompressSP, NULL);
+ return;
+ }
+
+ /* Image Type */
+ if (!strcmp(name, ImageTypeSP.name))
+ {
+ IUResetSwitches(&ImageTypeSP);
+ IUUpdateSwitches(&ImageTypeSP, states, names, n);
+ ImageTypeSP.s = IPS_OK;
+
+ IDSetSwitch(&ImageTypeSP, NULL);
+ return;
+ }
+
+ /* Video Stream */
+ if (!strcmp(name, StreamSP.name))
+ {
+
+ if (checkPowerS(&StreamSP))
+ return;
+
+ IUResetSwitches(&StreamSP);
+ IUUpdateSwitches(&StreamSP, states, names, n);
+ StreamSP.s = IPS_IDLE;
+
+
+ if (StreamS[0].s == ISS_ON)
+ {
+ frameCount = 0;
+ IDLog("Starting the video stream.\n");
+ v4l_base->start_capturing(errmsg);
+ StreamSP.s = IPS_BUSY;
+ }
+ else
+ {
+ IDLog("The video stream has been disabled. Frame count %d\n", frameCount);
+ v4l_base->stop_capturing(errmsg);
+ }
+
+ IDSetSwitch(&StreamSP, NULL);
+ return;
+ }
+
+}
+
+void V4L_Driver::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int /*n*/)
+{
+ IText *tp;
+
+
+ /* ignore if not ours */
+ if (dev && strcmp (device_name, dev))
+ return;
+
+ if (!strcmp(name, PortTP.name) )
+ {
+ PortTP.s = IPS_OK;
+ tp = IUFindText( &PortTP, names[0] );
+ if (!tp)
+ return;
+
+ IUSaveText(tp, texts[0]);
+ IDSetText (&PortTP, NULL);
+ return;
+ }
+}
+
+void V4L_Driver::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+ char errmsg[ERRMSGSIZ];
+
+ /* ignore if not ours */
+ if (dev && strcmp (device_name, dev))
+ return;
+
+
+ /* Frame Size */
+ if (!strcmp (FrameNP.name, name))
+ {
+ if (checkPowerN(&FrameNP))
+ return;
+
+ int oldW = (int) FrameN[2].value;
+ int oldH = (int) FrameN[3].value;
+
+ FrameNP.s = IPS_OK;
+
+ if (IUUpdateNumbers(&FrameNP, values, names, n) < 0)
+ return;
+
+ if (v4l_base->setSize( (int) FrameN[2].value, (int) FrameN[3].value) != -1)
+ {
+ FrameN[2].value = v4l_base->getWidth();
+ FrameN[3].value = v4l_base->getHeight();
+ IDSetNumber(&FrameNP, NULL);
+ return;
+ }
+ else
+ {
+ FrameN[2].value = oldW;
+ FrameN[3].value = oldH;
+ FrameNP.s = IPS_ALERT;
+ IDSetNumber(&FrameNP, "Failed to set a new image size.");
+ }
+
+ return;
+ }
+
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ /* Frame rate */
+ if (!strcmp (FrameRateNP.name, name))
+ {
+ if (checkPowerN(&FrameRateNP))
+ return;
+
+ FrameRateNP.s = IPS_IDLE;
+
+ if (IUUpdateNumbers(&FrameRateNP, values, names, n) < 0)
+ return;
+
+ v4l_base->setFPS( (int) FrameRateN[0].value );
+
+ FrameRateNP.s = IPS_OK;
+ IDSetNumber(&FrameRateNP, NULL);
+ return;
+ }
+ #endif
+
+
+ if (!strcmp (ImageAdjustNP.name, name))
+ {
+ if (checkPowerN(&ImageAdjustNP))
+ return;
+
+ ImageAdjustNP.s = IPS_IDLE;
+
+ if (IUUpdateNumbers(&ImageAdjustNP, values, names, n) < 0)
+ return;
+
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ v4l_base->setContrast( (int) (ImageAdjustN[0].value * divider));
+ v4l_base->setBrightness( (int) (ImageAdjustN[1].value * divider));
+ v4l_base->setHue( (int) (ImageAdjustN[2].value * divider));
+ v4l_base->setColor( (int) (ImageAdjustN[3].value * divider));
+ v4l_base->setWhiteness( (int) (ImageAdjustN[4].value * divider));
+
+ ImageAdjustN[0].value = v4l_base->getContrast() / divider;
+ ImageAdjustN[1].value = v4l_base->getBrightness() / divider;
+ ImageAdjustN[2].value = v4l_base->getHue() / divider;
+ ImageAdjustN[3].value = v4l_base->getColor() / divider;
+ ImageAdjustN[4].value = v4l_base->getWhiteness() / divider;
+
+ #else
+ unsigned int ctrl_id;
+ for (int i=0; i < ImageAdjustNP.nnp; i++)
+ {
+ ctrl_id = *((unsigned int *) ImageAdjustNP.np[i].aux0);
+ if (v4l_base->setINTControl( ctrl_id , ImageAdjustNP.np[i].value, errmsg) < 0)
+ {
+ ImageAdjustNP.s = IPS_ALERT;
+ IDSetNumber(&ImageAdjustNP, "Unable to adjust setting. %s", errmsg);
+ return;
+ }
+ }
+ #endif
+
+ ImageAdjustNP.s = IPS_OK;
+ IDSetNumber(&ImageAdjustNP, NULL);
+ return;
+ }
+
+
+ /* Exposure */
+ if (!strcmp (ExposeTimeNP.name, name))
+ {
+
+ if (checkPowerN(&ExposeTimeNP))
+ return;
+
+ if (StreamS[0].s == ISS_ON)
+ v4l_base->stop_capturing(errmsg);
+
+ StreamS[0].s = ISS_OFF;
+ StreamS[1].s = ISS_ON;
+ StreamSP.s = IPS_IDLE;
+ IDSetSwitch(&StreamSP, NULL);
+
+ V4LFrame->expose = 1000;
+
+ v4l_base->start_capturing(errmsg);
+ ExposeTimeNP.s = IPS_BUSY;
+ IDSetNumber(&ExposeTimeNP, NULL);
+
+ return;
+ }
+
+
+
+}
+
+void V4L_Driver::newFrame(void *p)
+{
+ ((V4L_Driver *) (p))->updateFrame();
+}
+
+void V4L_Driver::updateFrame()
+{
+ char errmsg[ERRMSGSIZ];
+ static int dropLarge = 3;
+
+ if (StreamSP.s == IPS_BUSY)
+ {
+ frameCount++;
+
+ // Drop some frames
+ if (FrameN[2].value > 160)
+ {
+ dropLarge--;
+ if (dropLarge == 0)
+ {
+ dropLarge = 3;
+ return;
+ }
+ else if (dropLarge < 2) return;
+
+ }
+
+ updateStream();
+ }
+ else if (ExposeTimeNP.s == IPS_BUSY)
+ {
+ V4LFrame->Y = v4l_base->getY();
+ v4l_base->stop_capturing(errmsg);
+ grabImage();
+ }
+
+}
+
+void V4L_Driver::updateStream()
+{
+
+ int width = v4l_base->getWidth();
+ int height = v4l_base->getHeight();
+ uLongf compressedBytes = 0;
+ uLong totalBytes;
+ unsigned char *targetFrame;
+ int r;
+
+ if (PowerS[0].s == ISS_OFF || StreamS[0].s == ISS_OFF) return;
+
+ if (ImageTypeS[0].s == ISS_ON)
+ V4LFrame->Y = v4l_base->getY();
+ else
+ V4LFrame->colorBuffer = v4l_base->getColorBuffer();
+
+ totalBytes = ImageTypeS[0].s == ISS_ON ? width * height : width * height * 4;
+ targetFrame = ImageTypeS[0].s == ISS_ON ? V4LFrame->Y : V4LFrame->colorBuffer;
+
+ /* Do we want to compress ? */
+ if (CompressS[0].s == ISS_ON)
+ {
+ /* Compress frame */
+ V4LFrame->compressedFrame = (unsigned char *) realloc (V4LFrame->compressedFrame, sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
+
+ compressedBytes = sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3;
+
+ r = compress2(V4LFrame->compressedFrame, &compressedBytes, targetFrame, totalBytes, 4);
+ if (r != Z_OK)
+ {
+ /* this should NEVER happen */
+ IDLog("internal error - compression failed: %d\n", r);
+ return;
+ }
+
+ /* #3.A Send it compressed */
+ imageB.blob = V4LFrame->compressedFrame;
+ imageB.bloblen = compressedBytes;
+ imageB.size = totalBytes;
+ strcpy(imageB.format, ".stream.z");
+ }
+ else
+ {
+ /* #3.B Send it uncompressed */
+ imageB.blob = targetFrame;
+ imageB.bloblen = totalBytes;
+ imageB.size = totalBytes;
+ strcpy(imageB.format, ".stream");
+ }
+
+ imageBP.s = IPS_OK;
+ IDSetBLOB (&imageBP, NULL);
+
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ char errmsg[ERRMSGSIZ];
+ v4l_base->start_capturing(errmsg);
+ #endif
+}
+
+/* Downloads the image from the CCD row by row and store them
+ in a raw file.
+ N.B. No processing is done on the image */
+int V4L_Driver::grabImage()
+{
+ int err, fd;
+ char errmsg[ERRMSG_SIZE];
+ char filename[] = "/tmp/fitsXXXXXX";
+
+
+ if ((fd = mkstemp(filename)) < 0)
+ {
+ IDMessage(device_name, "Error making temporary filename.");
+ IDLog("Error making temporary filename.\n");
+ return -1;
+ }
+ close(fd);
+
+ err = writeFITS(filename, errmsg);
+ if (err)
+ {
+ IDMessage(device_name, errmsg, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int V4L_Driver::writeFITS(const char * filename, char errmsg[])
+{
+ FITS_FILE* ofp;
+ int i, bpp, bpsl, width, height;
+ long nbytes;
+ FITS_HDU_LIST *hdu;
+
+ ofp = fits_open (filename, "w");
+ if (!ofp)
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "Error: cannot open file for writing.");
+ return (-1);
+ }
+
+ width = v4l_base->getWidth();
+ height = v4l_base->getHeight();
+ bpp = 1; /* Bytes per Pixel */
+ bpsl = bpp * width; /* Bytes per Line */
+ nbytes = 0;
+
+ hdu = create_fits_header (ofp, width, height, bpp);
+ if (hdu == NULL)
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "Error: creating FITS header failed.");
+ return (-1);
+ }
+ if (fits_write_header (ofp, hdu) < 0)
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "Error: writing to FITS header failed.");
+ return (-1);
+ }
+
+ for (i= height - 1; i >=0 ; i--)
+ {
+ fwrite(V4LFrame->Y + (i * width), 1, width, ofp->fp);
+ nbytes += bpsl;
+ }
+
+ nbytes = nbytes % FITS_RECORD_SIZE;
+ if (nbytes)
+ {
+ while (nbytes++ < FITS_RECORD_SIZE)
+ putc (0, ofp->fp);
+ }
+
+ if (ferror (ofp->fp))
+ {
+ snprintf(errmsg, ERRMSG_SIZE, "Error: write error occured");
+ return (-1);
+ }
+
+ fits_close (ofp);
+
+ /* Success */
+ ExposeTimeNP.s = IPS_OK;
+ IDSetNumber(&ExposeTimeNP, NULL);
+
+ uploadFile(filename);
+
+ return 0;
+
+}
+
+void V4L_Driver::uploadFile(const char * filename)
+{
+
+ FILE * fitsFile;
+ unsigned char *fitsData;
+ int r=0;
+ unsigned int nr = 0;
+ uLong totalBytes;
+ uLongf compressedBytes = 0;
+ struct stat stat_p;
+
+ if ( -1 == stat (filename, &stat_p))
+ {
+ IDLog(" Error occoured attempting to stat %s\n", filename);
+ return;
+ }
+
+ totalBytes = stat_p.st_size;
+ fitsData = new unsigned char[totalBytes];
+
+ fitsFile = fopen(filename, "r");
+
+ if (fitsFile == NULL)
+ return;
+
+ /* #1 Read file from disk */
+ for (unsigned int i=0; i < totalBytes; i+= nr)
+ {
+ nr = fread(fitsData + i, 1, totalBytes - i, fitsFile);
+
+ if (nr <= 0)
+ {
+ IDLog("Error reading temporary FITS file.\n");
+ return;
+ }
+ }
+
+ if (CompressS[0].s == ISS_ON)
+ {
+ /* #2 Compress it */
+ V4LFrame->compressedFrame = (unsigned char *) realloc (V4LFrame->compressedFrame, sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3);
+
+ compressedBytes = sizeof(unsigned char) * totalBytes + totalBytes / 64 + 16 + 3;
+
+
+ r = compress2(V4LFrame->compressedFrame, &compressedBytes, fitsData, totalBytes, 9);
+ if (r != Z_OK)
+ {
+ /* this should NEVER happen */
+ IDLog("internal error - compression failed: %d\n", r);
+ return;
+ }
+
+ /* #3.A Send it compressed */
+ imageB.blob = V4LFrame->compressedFrame;
+ imageB.bloblen = compressedBytes;
+ imageB.size = totalBytes;
+ strcpy(imageB.format, ".fits.z");
+ }
+ else
+ {
+ imageB.blob = fitsData;
+ imageB.bloblen = totalBytes;
+ imageB.size = totalBytes;
+ strcpy(imageB.format, ".fits");
+ }
+
+ imageBP.s = IPS_OK;
+ IDSetBLOB (&imageBP, NULL);
+
+ delete (fitsData);
+}
+
+void V4L_Driver::connectCamera()
+{
+ char errmsg[ERRMSGSIZ];
+
+
+ switch (PowerS[0].s)
+ {
+ case ISS_ON:
+ if (v4l_base->connectCam(PortT[0].text, errmsg) < 0)
+ {
+ PowerSP.s = IPS_IDLE;
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ IDSetSwitch(&PowerSP, "Error: unable to open device");
+ IDLog("Error: %s\n", errmsg);
+ return;
+ }
+
+ /* Sucess! */
+ PowerS[0].s = ISS_ON;
+ PowerS[1].s = ISS_OFF;
+ PowerSP.s = IPS_OK;
+ IDSetSwitch(&PowerSP, "Video4Linux Generic Device is online. Retrieving basic data.");
+
+ v4l_base->registerCallback(newFrame, this);
+
+ V4LFrame->compressedFrame = (unsigned char *) malloc (sizeof(unsigned char) * 1);
+
+ IDLog("V4L Device is online. Retrieving basic data.\n");
+ getBasicData();
+
+ break;
+
+ case ISS_OFF:
+ PowerS[0].s = ISS_OFF;
+ PowerS[1].s = ISS_ON;
+ PowerSP.s = IPS_IDLE;
+
+ free(V4LFrame->compressedFrame);
+ V4LFrame->compressedFrame = NULL;
+ v4l_base->disconnectCam();
+
+ IDSetSwitch(&PowerSP, "Video4Linux Generic Device is offline.");
+
+ break;
+ }
+}
+
+/* Retrieves basic data from the device upon connection.*/
+void V4L_Driver::getBasicData()
+{
+
+ int xmax, ymax, xmin, ymin;
+
+ v4l_base->getMaxMinSize(xmax, ymax, xmin, ymin);
+
+ /* Width */
+ FrameN[2].value = v4l_base->getWidth();
+ FrameN[2].min = xmin;
+ FrameN[2].max = xmax;
+
+ /* Height */
+ FrameN[3].value = v4l_base->getHeight();
+ FrameN[3].min = ymin;
+ FrameN[3].max = ymax;
+
+ IUUpdateMinMax(&FrameNP);
+ IDSetNumber(&FrameNP, NULL);
+
+ IUSaveText(&camNameT[0], v4l_base->getDeviceName());
+ IDSetText(&camNameTP, NULL);
+
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ updateV4L1Controls();
+ #else
+ updateV4L2Controls();
+ #endif
+
+}
+
+#ifdef HAVE_LINUX_VIDEODEV2_H
+void V4L_Driver::updateV4L2Controls()
+{
+ // #1 Query for INTEGER controls, and fill up the structure
+ free(ImageAdjustNP.np);
+ ImageAdjustNP.nnp = 0;
+
+ if (v4l_base->queryINTControls(&ImageAdjustNP) > 0)
+ IDDefNumber(&ImageAdjustNP, NULL);
+}
+#else
+void V4L_Driver::updateV4L1Controls()
+{
+
+ if ( (v4l_base->getContrast() / divider) > ImageAdjustN[0].max)
+ divider *=2;
+
+ if ( (v4l_base->getHue() / divider) > ImageAdjustN[2].max)
+ divider *=2;
+
+ ImageAdjustN[0].value = v4l_base->getContrast() / divider;
+ ImageAdjustN[1].value = v4l_base->getBrightness() / divider;
+ ImageAdjustN[2].value = v4l_base->getHue() / divider;
+ ImageAdjustN[3].value = v4l_base->getColor() / divider;
+ ImageAdjustN[4].value = v4l_base->getWhiteness() / divider;
+
+ ImageAdjustNP.s = IPS_OK;
+ IDSetNumber(&ImageAdjustNP, NULL);
+
+}
+#endif
+
+int V4L_Driver::checkPowerS(ISwitchVectorProperty *sp)
+{
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(sp->label, ""))
+ IDMessage (device_name, "Cannot change property %s while the camera is offline.", sp->name);
+ else
+ IDMessage (device_name, "Cannot change property %s while the camera is offline.", sp->label);
+
+ sp->s = IPS_IDLE;
+ IDSetSwitch(sp, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int V4L_Driver::checkPowerN(INumberVectorProperty *np)
+{
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(np->label, ""))
+ IDMessage (device_name, "Cannot change property %s while the camera is offline.", np->name);
+ else
+ IDMessage (device_name, "Cannot change property %s while the camera is offline.", np->label);
+
+ np->s = IPS_IDLE;
+ IDSetNumber(np, NULL);
+ return -1;
+ }
+
+ return 0;
+}
+
+int V4L_Driver::checkPowerT(ITextVectorProperty *tp)
+{
+
+ if (PowerSP.s != IPS_OK)
+ {
+ if (!strcmp(tp->label, ""))
+ IDMessage (device_name, "Cannot change property %s while the camera is offline.", tp->name);
+ else
+ IDMessage (device_name, "Cannot change property %s while the camera is offline.", tp->label);
+
+ tp->s = IPS_IDLE;
+ IDSetText(tp, NULL);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+FITS_HDU_LIST * V4L_Driver::create_fits_header (FITS_FILE *ofp, uint width, uint height, uint bpp)
+{
+
+ FITS_HDU_LIST *hdulist;
+ char expose_s[80];
+ char obsDate[80];
+ char instrumentName[80];
+ char ts[32];
+
+ struct tm *tp;
+ time_t t;
+ time (&t);
+ tp = gmtime (&t);
+ strftime (ts, sizeof(ts), "%Y-%m-%dT%H:%M:%S", tp);
+
+ snprintf(instrumentName, 80, "INSTRUME= '%s'", v4l_base->getDeviceName());
+ snprintf(obsDate, 80, "DATE-OBS= '%s' /Observation Date UTC", ts);
+
+ hdulist = fits_add_hdu (ofp);
+ if (hdulist == NULL) return (NULL);
+
+ hdulist->used.simple = 1;
+ hdulist->bitpix = 8;
+ hdulist->naxis = 2;
+ hdulist->naxisn[0] = width;
+ hdulist->naxisn[1] = height;
+ hdulist->naxisn[2] = bpp;
+ hdulist->used.datamin = 0;
+ hdulist->used.datamax = 0;
+ hdulist->used.bzero = 1;
+ hdulist->bzero = 0.0;
+ hdulist->used.bscale = 1;
+ hdulist->bscale = 1.0;
+
+ snprintf(expose_s, sizeof(expose_s), "EXPOSURE= %d / milliseconds", V4LFrame->expose);
+
+ fits_add_card (hdulist, expose_s);
+ fits_add_card (hdulist, instrumentName);
+ fits_add_card (hdulist, obsDate);
+
+ return (hdulist);
+}
+
+
+
diff --git a/kstars/kstars/indi/v4ldriver.h b/kstars/kstars/indi/v4ldriver.h
new file mode 100644
index 00000000..9e7936e7
--- /dev/null
+++ b/kstars/kstars/indi/v4ldriver.h
@@ -0,0 +1,171 @@
+#if 0
+ V4L INDI Driver
+ INDI Interface for V4L devices
+ Copyright (C) 2003-2005 Jasem Mutlaq (mutlaqja@ikarustech.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#endif
+
+#ifndef V4L_DRIVER_H
+#define V4L_DRIVER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <zlib.h>
+#include <asm/types.h>
+
+#include "indidevapi.h"
+#include "indicom.h"
+#include "fitsrw.h"
+#include "eventloop.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LINUX_VIDEODEV2_H
+#include "webcam/v4l2_base.h"
+#else
+#include "webcam/v4l1_base.h"
+#endif
+
+#define COMM_GROUP "Main Control"
+#define IMAGE_CONTROL "Image Control"
+#define IMAGE_GROUP "Image Settings"
+
+#define MAX_PIXELS 4096 /* Max number of pixels in one dimension */
+#define ERRMSGSIZ 1024
+
+
+class V4L_Driver
+{
+ public:
+ V4L_Driver();
+ virtual ~V4L_Driver();
+
+ /* INDI Functions that must be called from indidrivermain */
+ virtual void ISGetProperties (const char *dev);
+ virtual void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+ virtual void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ virtual void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+
+ virtual void initCamBase();
+ virtual void initProperties(const char *dev);
+
+ static void newFrame(void *p);
+ void updateFrame();
+
+ protected:
+
+ /* Structs */
+ typedef struct {
+ int width;
+ int height;
+ int expose;
+ unsigned char *Y;
+ unsigned char *U;
+ unsigned char *V;
+ unsigned char *colorBuffer;
+ unsigned char *compressedFrame;
+ } img_t;
+
+
+ /* Switches */
+ ISwitch PowerS[2];
+ ISwitch StreamS[2];
+ ISwitch CompressS[2];
+ ISwitch ImageTypeS[2];
+
+ /* Texts */
+ IText PortT[1];
+ IText camNameT[1];
+
+ /* Numbers */
+ INumber ExposeTimeN[1];
+ INumber FrameRateN[1];
+ INumber FrameN[4];
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ INumber ImageAdjustN[5];
+ #endif
+
+ /* BLOBs */
+ IBLOB imageB;
+
+ /* Switch vectors */
+ ISwitchVectorProperty PowerSP; /* Connection switch */
+ ISwitchVectorProperty StreamSP; /* Stream switch */
+ ISwitchVectorProperty CompressSP; /* Compress stream switch */
+ ISwitchVectorProperty ImageTypeSP; /* Color or grey switch */
+
+ /* Number vectors */
+ INumberVectorProperty ExposeTimeNP; /* Exposure */
+ INumberVectorProperty FrameRateNP; /* Frame rate */
+ INumberVectorProperty FrameNP; /* Stream dimenstion */
+ INumberVectorProperty ImageAdjustNP; /* Image controls */
+
+ /* Text vectors */
+ ITextVectorProperty PortTP;
+ ITextVectorProperty camNameTP;
+
+ /* BLOB vectors */
+ IBLOBVectorProperty imageBP; /* Data stream */
+
+ /* Initilization functions */
+ virtual void connectCamera(void);
+ virtual void getBasicData(void);
+
+ /* Stream/FITS functions */
+ void updateStream();
+ void uploadFile(const char * filename);
+ int writeFITS(const char *filename, char errmsg[]);
+ int grabImage(void);
+ FITS_HDU_LIST * create_fits_header (FITS_FILE *ofp, uint width, uint height, uint bpp);
+
+ /* Helper functions */
+ int checkPowerN(INumberVectorProperty *np);
+ int checkPowerS(ISwitchVectorProperty *sp);
+ int checkPowerT(ITextVectorProperty *tp);
+
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ virtual void updateV4L1Controls();
+ V4L1_Base *v4l_base;
+ #else
+ virtual void updateV4L2Controls();
+ V4L2_Base *v4l_base;
+ #endif
+
+ char device_name[MAXINDIDEVICE];
+ int frameCount; /* For debugging */
+ double divider; /* For limits */
+ img_t * V4LFrame; /* Video frame */
+
+};
+
+#endif
diff --git a/kstars/kstars/indi/v4lphilips.cpp b/kstars/kstars/indi/v4lphilips.cpp
new file mode 100644
index 00000000..cc15d43d
--- /dev/null
+++ b/kstars/kstars/indi/v4lphilips.cpp
@@ -0,0 +1,610 @@
+/*
+ Phlips webcam INDI driver
+ Copyright (C) 2003-2005 by Jasem Mutlaq
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ 2005.04.29 JM: There is no need for this file for Video 4 Linux 2. It is kept for V4L 1 compatiblity.
+
+*/
+
+#include "v4lphilips.h"
+#include "webcam/pwc-ioctl.h"
+
+V4L_Philips::V4L_Philips() : V4L_Driver()
+{
+
+}
+
+V4L_Philips::~V4L_Philips()
+{
+
+}
+
+void V4L_Philips::initCamBase()
+{
+ #ifdef HAVE_LINUX_VIDEODEV2_H
+ v4l_base = new V4L2_Base();
+ #else
+ v4l_pwc = new V4L1_PWC();
+ v4l_base = (V4L1_Base *) v4l_pwc;
+ #endif
+}
+
+void V4L_Philips::initProperties(const char *dev)
+{
+
+ // Call parent
+ V4L_Driver::initProperties(dev);
+
+ fillSwitch(&BackLightS[0], "ON", "", ISS_OFF);
+ fillSwitch(&BackLightS[1], "OFF", "", ISS_ON);
+ fillSwitchVector(&BackLightSP, BackLightS, NARRAY(BackLightS), dev, "Back Light", "", IMAGE_CONTROL, IP_RW, ISR_1OFMANY, 0 , IPS_IDLE);
+
+ fillSwitch(&AntiFlickerS[0], "ON", "", ISS_OFF);
+ fillSwitch(&AntiFlickerS[1], "OFF", "", ISS_ON);
+ fillSwitchVector(&AntiFlickerSP, AntiFlickerS, NARRAY(AntiFlickerS), dev, "Anti Flicker", "", IMAGE_CONTROL, IP_RW, ISR_1OFMANY, 0 , IPS_IDLE);
+
+ fillSwitch(&NoiseReductionS[0], "None", "", ISS_ON);
+ fillSwitch(&NoiseReductionS[1], "Low", "", ISS_OFF);
+ fillSwitch(&NoiseReductionS[2], "Medium", "", ISS_OFF);
+ fillSwitch(&NoiseReductionS[3], "High", "", ISS_OFF);
+ fillSwitchVector(&NoiseReductionSP, NoiseReductionS, NARRAY(NoiseReductionS), dev, "Noise Reduction", "", IMAGE_CONTROL, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ fillSwitch(&CamSettingS[0], "Save", "", ISS_OFF);
+ fillSwitch(&CamSettingS[1], "Restore", "", ISS_OFF);
+ fillSwitch(&CamSettingS[2], "Factory", "", ISS_OFF);
+ fillSwitchVector(&CamSettingSP, CamSettingS, NARRAY(CamSettingS), dev, "Settings", "", IMAGE_CONTROL, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ fillSwitch(&WhiteBalanceModeS[0], "Auto" , "", ISS_ON);
+ fillSwitch(&WhiteBalanceModeS[1], "Manual" , "", ISS_OFF);
+ fillSwitch(&WhiteBalanceModeS[2], "Indoor" , "", ISS_OFF);
+ fillSwitch(&WhiteBalanceModeS[3], "Outdoor" , "", ISS_OFF);
+ fillSwitch(&WhiteBalanceModeS[4], "Fluorescent" , "", ISS_OFF);
+
+ fillSwitchVector(&WhiteBalanceModeSP, WhiteBalanceModeS, NARRAY(WhiteBalanceModeS), dev, "White Balance Mode", "", IMAGE_CONTROL, IP_RW, ISR_1OFMANY, 0, IPS_IDLE);
+
+ fillNumber(&WhiteBalanceN[0], "Manual Red", "", "%0.f", 0., 256., 1., 0.);
+ fillNumber(&WhiteBalanceN[1], "Manual Blue", "", "%0.f", 0., 256., 1., 0.);
+ fillNumberVector(&WhiteBalanceNP, WhiteBalanceN, NARRAY(WhiteBalanceN), dev, "White Balance", "", IMAGE_CONTROL, IP_RW, 60, IPS_IDLE);
+
+ fillNumber(&ShutterSpeedN[0], "Speed", "", "%0.f", 0., 65535., 100., 0.);
+ fillNumberVector(&ShutterSpeedNP, ShutterSpeedN, NARRAY(ShutterSpeedN), dev, "Shutter Speed", "", COMM_GROUP, IP_RW, 60, IPS_IDLE);
+
+}
+
+void V4L_Philips::ISGetProperties (const char *dev)
+{
+
+ if (dev && strcmp (device_name, dev))
+ return;
+
+ #ifdef HAVE_LINUX_VIDEODEV2_H
+ V4L_Driver::ISGetProperties(dev);
+ return;
+ #endif
+
+ /* COMM_GROUP */
+ IDDefSwitch(&PowerSP, NULL);
+ IDDefText(&PortTP, NULL);
+ IDDefText(&camNameTP, NULL);
+ IDDefSwitch(&StreamSP, NULL);
+ IDDefNumber(&FrameRateNP, NULL);
+ IDDefNumber(&ExposeTimeNP, NULL);
+ IDDefNumber(&ShutterSpeedNP, NULL);
+ IDDefBLOB(&imageBP, NULL);
+
+ /* Image Groups */
+ IDDefSwitch(&CompressSP, NULL);
+ IDDefSwitch(&ImageTypeSP, NULL);
+ IDDefNumber(&FrameNP, NULL);
+ IDDefNumber(&ImageAdjustNP, NULL);
+
+ /* Image Control */
+ IDDefSwitch(&WhiteBalanceModeSP, NULL);
+ IDDefNumber(&WhiteBalanceNP, NULL);
+ IDDefSwitch(&BackLightSP, NULL);
+ IDDefSwitch(&AntiFlickerSP, NULL);
+ IDDefSwitch(&NoiseReductionSP, NULL);
+ IDDefSwitch(&CamSettingSP, NULL);
+
+}
+
+void V4L_Philips::ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n)
+{
+ char errmsg[ERRMSG_SIZE];
+ int index=0;
+
+ /* ignore if not ours */
+ if (dev && strcmp (device_name, dev))
+ return;
+
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ /* Anti Flicker control */
+ if (!strcmp (AntiFlickerSP.name, name))
+ {
+ if (checkPowerS(&AntiFlickerSP))
+ return;
+
+ AntiFlickerSP.s = IPS_IDLE;
+
+ IUResetSwitches(&AntiFlickerSP);
+ IUUpdateSwitches(&AntiFlickerSP, states, names, n);
+
+ if (AntiFlickerS[0].s == ISS_ON)
+ {
+ if (v4l_pwc->setFlicker(true, errmsg) < 0)
+ {
+ AntiFlickerS[0].s = ISS_OFF;
+ AntiFlickerS[1].s = ISS_ON;
+ IDSetSwitch(&AntiFlickerSP, "%s", errmsg);
+ return;
+ }
+
+ AntiFlickerSP.s = IPS_OK;
+ IDSetSwitch(&AntiFlickerSP, NULL);
+ }
+ else
+ {
+ if (v4l_pwc->setFlicker(false, errmsg) < 0)
+ {
+ AntiFlickerS[0].s = ISS_ON;
+ AntiFlickerS[1].s = ISS_OFF;
+ IDSetSwitch(&AntiFlickerSP, "%s", errmsg);
+ return;
+ }
+
+ IDSetSwitch(&AntiFlickerSP, NULL);
+ }
+
+ return;
+ }
+
+ /* Back light compensation */
+ if (!strcmp (BackLightSP.name, name))
+ {
+ if (checkPowerS(&BackLightSP))
+ return;
+
+ BackLightSP.s = IPS_IDLE;
+
+ IUResetSwitches(&BackLightSP);
+ IUUpdateSwitches(&BackLightSP, states, names, n);
+
+ if (BackLightS[0].s == ISS_ON)
+ {
+ if (v4l_pwc->setBackLight(true, errmsg) < 0)
+ {
+ BackLightS[0].s = ISS_OFF;
+ BackLightS[1].s = ISS_ON;
+ IDSetSwitch(&BackLightSP, "%s", errmsg);
+ return;
+ }
+
+ BackLightSP.s = IPS_OK;
+ IDSetSwitch(&BackLightSP, NULL);
+ }
+ else
+ {
+ if (v4l_pwc->setBackLight(false, errmsg) < 0)
+ {
+ BackLightS[0].s = ISS_ON;
+ BackLightS[1].s = ISS_OFF;
+ IDSetSwitch(&BackLightSP, "%s", errmsg);
+ return;
+ }
+
+ IDSetSwitch(&BackLightSP, NULL);
+ }
+
+ return;
+ }
+
+ /* Noise reduction control */
+ if (!strcmp (NoiseReductionSP.name, name))
+ {
+ if (checkPowerS(&NoiseReductionSP))
+ return;
+
+ NoiseReductionSP.s = IPS_IDLE;
+
+ IUResetSwitches(&NoiseReductionSP);
+ IUUpdateSwitches(&NoiseReductionSP, states, names, n);
+
+ for (int i=0; i < 4; i++)
+ if (NoiseReductionS[i].s == ISS_ON)
+ {
+ index = i;
+ break;
+ }
+
+ if (v4l_pwc->setNoiseRemoval(index, errmsg) < 0)
+ {
+ IUResetSwitches(&NoiseReductionSP);
+ NoiseReductionS[0].s = ISS_ON;
+ IDSetSwitch(&NoiseReductionSP, "%s", errmsg);
+ return;
+ }
+
+ NoiseReductionSP.s = IPS_OK;
+
+ IDSetSwitch(&NoiseReductionSP, NULL);
+ return;
+ }
+
+ /* White balace mode */
+ if (!strcmp (WhiteBalanceModeSP.name, name))
+ {
+ if (checkPowerS(&WhiteBalanceModeSP))
+ return;
+
+ WhiteBalanceModeSP.s = IPS_IDLE;
+
+ IUResetSwitches(&WhiteBalanceModeSP);
+ IUUpdateSwitches(&WhiteBalanceModeSP, states, names, n);
+
+ for (int i=0; i < 5; i++)
+ if (WhiteBalanceModeS[i].s == ISS_ON)
+ {
+ index = i;
+ break;
+ }
+
+ switch (index)
+ {
+ // Auto
+ case 0:
+ if (v4l_pwc->setWhiteBalanceMode(PWC_WB_AUTO, errmsg) < 0)
+ {
+ IUResetSwitches(&WhiteBalanceModeSP),
+ WhiteBalanceModeS[0].s = ISS_ON;
+ IDSetSwitch(&WhiteBalanceModeSP, "%s", errmsg);
+ return;
+ }
+ break;
+
+ // Manual
+ case 1:
+ if (v4l_pwc->setWhiteBalanceMode(PWC_WB_MANUAL, errmsg) < 0)
+ {
+ IUResetSwitches(&WhiteBalanceModeSP),
+ WhiteBalanceModeS[0].s = ISS_ON;
+ IDSetSwitch(&WhiteBalanceModeSP, "%s", errmsg);
+ return;
+ }
+ break;
+
+ // Indoor
+ case 2:
+ if (v4l_pwc->setWhiteBalanceMode(PWC_WB_INDOOR, errmsg) < 0)
+ {
+ IUResetSwitches(&WhiteBalanceModeSP),
+ WhiteBalanceModeS[0].s = ISS_ON;
+ IDSetSwitch(&WhiteBalanceModeSP, "%s", errmsg);
+ return;
+ }
+ break;
+
+ // Outdoor
+ case 3:
+ if (v4l_pwc->setWhiteBalanceMode(PWC_WB_OUTDOOR, errmsg) < 0)
+ {
+ IUResetSwitches(&WhiteBalanceModeSP),
+ WhiteBalanceModeS[0].s = ISS_ON;
+ IDSetSwitch(&WhiteBalanceModeSP, "%s", errmsg);
+ return;
+ }
+ break;
+
+ // Flurescent
+ case 4:
+ if (v4l_pwc->setWhiteBalanceMode(PWC_WB_FL, errmsg) < 0)
+ {
+ IUResetSwitches(&WhiteBalanceModeSP),
+ WhiteBalanceModeS[0].s = ISS_ON;
+ IDSetSwitch(&WhiteBalanceModeSP, "%s", errmsg);
+ return;
+ }
+ break;
+
+ }
+
+ WhiteBalanceModeSP.s = IPS_OK;
+ IDSetSwitch(&WhiteBalanceModeSP, NULL);
+ return;
+
+ }
+
+ /* Camera setttings */
+ if (!strcmp (CamSettingSP.name, name))
+ {
+
+ if (checkPowerS(&CamSettingSP))
+ return;
+
+ CamSettingSP.s = IPS_IDLE;
+
+ IUResetSwitches(&CamSettingSP);
+ IUUpdateSwitches(&CamSettingSP, states, names, n);
+
+ if (CamSettingS[0].s == ISS_ON)
+ {
+ if (v4l_pwc->saveSettings(errmsg) < 0)
+ {
+ IUResetSwitches(&CamSettingSP);
+ IDSetSwitch(&CamSettingSP, "%s", errmsg);
+ return;
+ }
+
+ CamSettingSP.s = IPS_OK;
+ IDSetSwitch(&CamSettingSP, "Settings saved.");
+ return;
+ }
+
+ if (CamSettingS[1].s == ISS_ON)
+ {
+ v4l_pwc->restoreSettings();
+ IUResetSwitches(&CamSettingSP);
+ CamSettingSP.s = IPS_OK;
+ IDSetSwitch(&CamSettingSP, "Settings restored.");
+ updateV4L1Controls();
+ return;
+ }
+
+ if (CamSettingS[2].s == ISS_ON)
+ {
+ v4l_pwc->restoreFactorySettings();
+ IUResetSwitches(&CamSettingSP);
+ CamSettingSP.s = IPS_OK;
+ IDSetSwitch(&CamSettingSP, "Factory settings restored.");
+ updateV4L1Controls();
+ return;
+ }
+ }
+ #endif
+
+ // Call parent
+ V4L_Driver::ISNewSwitch(dev, name, states, names, n);
+
+
+
+}
+
+void V4L_Philips::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
+{
+
+ V4L_Driver::ISNewText(dev, name, texts, names, n);
+
+}
+
+void V4L_Philips::ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n)
+{
+
+ // Nothing for V4L 2 to do here
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ char errmsg[ERRMSGSIZ];
+
+ /* Frame rate */
+ if (!strcmp (FrameRateNP.name, name))
+ {
+ if (checkPowerN(&FrameRateNP))
+ return;
+
+ FrameRateNP.s = IPS_IDLE;
+
+ int oldFP = (int) FrameRateN[0].value;
+
+ if (IUUpdateNumbers(&FrameRateNP, values, names, n) < 0)
+ return;
+
+ if (v4l_pwc->setFrameRate( (int) FrameRateN[0].value, errmsg) < 0)
+ {
+ FrameRateN[0].value = oldFP;
+ IDSetNumber(&FrameRateNP, "%s", errmsg);
+ return;
+ }
+
+ FrameRateNP.s = IPS_OK;
+ IDSetNumber(&FrameRateNP, NULL);
+ return;
+ }
+
+ if (!strcmp (ShutterSpeedNP.name, name))
+ {
+ if (checkPowerN(&ShutterSpeedNP))
+ return;
+
+ ShutterSpeedNP.s = IPS_IDLE;
+
+ if (v4l_pwc->setExposure( (int) values[0], errmsg) < 0)
+ {
+ IDSetNumber(&ShutterSpeedNP, "%s", errmsg);
+ return;
+ }
+
+ ShutterSpeedN[0].value = values[0];
+ ShutterSpeedNP.s = IPS_OK;
+ IDSetNumber(&ShutterSpeedNP, NULL);
+ return;
+ }
+
+ /* White balance */
+ if (!strcmp (WhiteBalanceNP.name, name))
+ {
+ if (checkPowerN(&WhiteBalanceNP))
+ return;
+
+ WhiteBalanceNP.s = IPS_IDLE;
+
+ int oldBalance[2];
+ oldBalance[0] = (int) WhiteBalanceN[0].value;
+ oldBalance[1] = (int) WhiteBalanceN[1].value;
+
+ if (IUUpdateNumbers(&WhiteBalanceNP, values, names, n) < 0)
+ return;
+
+ if (v4l_pwc->setWhiteBalanceRed( (int) WhiteBalanceN[0].value * 256, errmsg))
+ {
+ WhiteBalanceN[0].value = oldBalance[0];
+ WhiteBalanceN[1].value = oldBalance[1];
+ IDSetNumber(&WhiteBalanceNP, "%s", errmsg);
+ return;
+ }
+ if (v4l_pwc->setWhiteBalanceBlue( (int) WhiteBalanceN[1].value * 256, errmsg))
+ {
+ WhiteBalanceN[0].value = oldBalance[0];
+ WhiteBalanceN[1].value = oldBalance[1];
+ IDSetNumber(&WhiteBalanceNP, "%s", errmsg);
+ return;
+ }
+
+ IUResetSwitches(&WhiteBalanceModeSP);
+ WhiteBalanceModeS[1].s = ISS_ON;
+ WhiteBalanceModeSP.s = IPS_OK;
+ WhiteBalanceNP.s = IPS_OK;
+ IDSetSwitch(&WhiteBalanceModeSP, NULL);
+ IDSetNumber(&WhiteBalanceNP, NULL);
+ return;
+ }
+
+ #endif
+
+ // Call parent
+ V4L_Driver::ISNewNumber(dev, name, values, names, n);
+
+}
+
+#ifndef HAVE_LINUX_VIDEODEV2_H
+/* Retrieves basic data from the device upon connection.*/
+void V4L_Philips::getBasicData()
+{
+
+ char errmsg[ERRMSGSIZ];
+ bool result;
+ int xmax, ymax, xmin, ymin, index;
+
+ v4l_pwc->getMaxMinSize(xmax, ymax, xmin, ymin);
+
+ /* Width */
+ FrameN[2].value = v4l_pwc->getWidth();
+ FrameN[2].min = xmin;
+ FrameN[2].max = xmax;
+
+ /* Height */
+ FrameN[3].value = v4l_pwc->getHeight();
+ FrameN[3].min = ymin;
+ FrameN[3].max = ymax;
+
+ IDSetNumber(&FrameNP, NULL);
+ IUUpdateMinMax(&FrameNP);
+
+ IUSaveText(&camNameT[0], v4l_pwc->getDeviceName());
+ IDSetText(&camNameTP, NULL);
+
+ IDLog("Raw values\n Contrast: %d \n Brightness %d \n Color %d \n Sharpness %d \n Gain %d \n Gamma %d \n", v4l_pwc->getContrast(), v4l_pwc->getBrightness(), v4l_pwc->getColor(), v4l_pwc->getSharpness(), v4l_pwc->getGain(), v4l_pwc->getGama());
+
+ updateV4L1Controls();
+
+ if (v4l_pwc->setFrameRate( (int) FrameRateN[0].value, errmsg) < 0)
+ {
+ FrameRateNP.s = IPS_ALERT;
+ IDSetNumber(&FrameRateNP, "%s", errmsg);
+ }
+ else
+ {
+ FrameRateNP.s = IPS_OK;
+ IDSetNumber(&FrameRateNP, NULL);
+ }
+
+ result = v4l_pwc->getBackLight();
+ if (result)
+ {
+ BackLightS[0].s = ISS_ON;
+ BackLightS[1].s = ISS_OFF;
+ }
+ else
+ {
+ BackLightS[0].s = ISS_OFF;
+ BackLightS[1].s = ISS_ON;
+ }
+ IDSetSwitch(&BackLightSP, NULL);
+
+ result = v4l_pwc->getFlicker();
+ if (result)
+ {
+ AntiFlickerS[0].s = ISS_ON;
+ AntiFlickerS[1].s = ISS_OFF;
+ }
+ else
+ {
+ AntiFlickerS[0].s = ISS_OFF;
+ AntiFlickerS[1].s = ISS_ON;
+ }
+ IDSetSwitch(&AntiFlickerSP, NULL);
+
+ index = v4l_pwc->getNoiseRemoval();
+ IUResetSwitches(&NoiseReductionSP);
+ NoiseReductionS[index].s = ISS_ON;
+ IDSetSwitch(&NoiseReductionSP, NULL);
+
+ index = v4l_pwc->getWhiteBalance();
+ IUResetSwitches(&WhiteBalanceModeSP);
+ switch (index)
+ {
+ case PWC_WB_AUTO:
+ WhiteBalanceModeS[0].s = ISS_ON;
+ break;
+ case PWC_WB_MANUAL:
+ WhiteBalanceModeS[1].s = ISS_ON;
+ break;
+ case PWC_WB_INDOOR:
+ WhiteBalanceModeS[2].s = ISS_ON;
+ break;
+ case PWC_WB_OUTDOOR:
+ WhiteBalanceModeS[3].s = ISS_ON;
+ break;
+ case PWC_WB_FL:
+ WhiteBalanceModeS[3].s = ISS_ON;
+ break;
+ }
+ IDSetSwitch(&WhiteBalanceModeSP, NULL);
+
+}
+#endif
+
+#ifndef HAVE_LINUX_VIDEODEV2_H
+void V4L_Philips::updateV4L1Controls()
+{
+ int index =0;
+
+ ImageAdjustN[0].value = v4l_pwc->getContrast() / 256.;
+ ImageAdjustN[1].value = v4l_pwc->getBrightness() / 256.;
+ ImageAdjustN[2].value = v4l_pwc->getColor() / 256.;
+ index = v4l_pwc->getSharpness();
+ if (index < 0)
+ ImageAdjustN[3].value = -1;
+ else
+ ImageAdjustN[3].value = v4l_pwc->getSharpness() / 256.;
+
+ ImageAdjustN[4].value = v4l_pwc->getGain() / 256.;
+ ImageAdjustN[5].value = v4l_pwc->getGama() / 256.;
+
+ ImageAdjustNP.s = IPS_OK;
+ IDSetNumber(&ImageAdjustNP, NULL);
+
+
+}
+#endif
+
diff --git a/kstars/kstars/indi/v4lphilips.h b/kstars/kstars/indi/v4lphilips.h
new file mode 100644
index 00000000..59c33f0a
--- /dev/null
+++ b/kstars/kstars/indi/v4lphilips.h
@@ -0,0 +1,77 @@
+/*
+ Phlips webcam INDI driver
+ Copyright (C) 2003-2005 by Jasem Mutlaq
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ 2005.04.29 JM: There is no need for this file for Video 4 Linux 2. It is kept for V4L 1 compatiblity.
+
+*/
+
+#ifndef HAVE_LINUX_VIDEODEV2_H
+#include "webcam/v4l1_pwc.h"
+#endif
+
+#include "v4ldriver.h"
+
+class V4L_Philips : public V4L_Driver
+{
+ public:
+ V4L_Philips();
+ ~V4L_Philips();
+
+ /* INDI Functions that must be called from indidrivermain */
+ void ISGetProperties (const char *dev);
+ void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n);
+ void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
+ void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n);
+
+ void initCamBase();
+ void initProperties(const char *dev);
+
+ private:
+
+ /* Switches */
+ ISwitch BackLightS[2];
+ ISwitch AntiFlickerS[2];
+ ISwitch NoiseReductionS[4];
+ ISwitch CamSettingS[3];
+ ISwitch WhiteBalanceModeS[5];
+
+
+ /* Nmubers */
+ INumber WhiteBalanceN[2];
+ INumber ShutterSpeedN[1];
+
+ /* Switch Vectors */
+ ISwitchVectorProperty BackLightSP;
+ ISwitchVectorProperty AntiFlickerSP;
+ ISwitchVectorProperty NoiseReductionSP;
+ ISwitchVectorProperty CamSettingSP;
+ ISwitchVectorProperty WhiteBalanceModeSP;
+
+ /* Number Vectors */
+ INumberVectorProperty WhiteBalanceNP;
+ INumberVectorProperty ShutterSpeedNP;
+
+ #ifndef HAVE_LINUX_VIDEODEV2_H
+ V4L1_PWC * v4l_pwc;
+ void updateV4L1Controls();
+ void getBasicData(void);
+ #endif
+
+};
+
+
diff --git a/kstars/kstars/indi/webcam/Makefile.am b/kstars/kstars/indi/webcam/Makefile.am
new file mode 100644
index 00000000..565859da
--- /dev/null
+++ b/kstars/kstars/indi/webcam/Makefile.am
@@ -0,0 +1,16 @@
+if HAVE_V4L2
+ libwebcam_linux = libwebcam_v4l2_linux.la
+else
+ libwebcam_linux = libwebcam_v4l1_linux.la
+endif
+
+noinst_LTLIBRARIES = libwebcam.la $(libwebcam_linux)
+
+libwebcam_v4l1_linux_la_SOURCES = PPort.cpp port.cpp v4l1_base.cpp v4l1_pwc.cpp ccvt_c2.c ccvt_misc.c
+libwebcam_v4l2_linux_la_SOURCES = PPort.cpp port.cpp v4l2_base.cpp ccvt_c2.c ccvt_misc.c
+
+libwebcam_la_SOURCES = empty_file.cpp
+libwebcam_la_LIBADD = $(libwebcam_linux)
+
+empty_file.cpp:
+ echo > empty_file.cpp
diff --git a/kstars/kstars/indi/webcam/PPort.cpp b/kstars/kstars/indi/webcam/PPort.cpp
new file mode 100644
index 00000000..b222a6f6
--- /dev/null
+++ b/kstars/kstars/indi/webcam/PPort.cpp
@@ -0,0 +1,107 @@
+/*
+ Copyright (C) 2004 by Jasem Mutlaq
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include "PPort.h"
+#include "port.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <iostream>
+
+using namespace std;
+
+#define TEST_VALIDITY {if (this==NULL) return false;}
+
+PPort::PPort() {
+ reset();
+}
+
+PPort::PPort(int ioPort) {
+ reset();
+ setPort(ioPort);
+}
+
+void PPort::reset() {
+ bitArray=0;
+ for (int i=0;i<8;++i) {
+ assignedBit[i]=NULL;
+ }
+ currentPort=NULL;
+}
+
+bool PPort::setPort(int ioPort) {
+ TEST_VALIDITY;
+ if (geteuid() != 0) {
+ cerr << "must be setuid root control parallel port"<<endl;
+ return false;
+ }
+ if (currentPort) {
+ delete currentPort;
+ }
+ reset();
+ currentPort=new port_t(ioPort);
+ return commit();
+}
+
+bool PPort::commit() {
+ TEST_VALIDITY;
+ if (currentPort) {
+ currentPort->write_data(bitArray);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool PPort::setBit(const void * ID,int bit,bool stat) {
+ TEST_VALIDITY;
+ if (ID != assignedBit[bit]) {
+ return false;
+ }
+
+ if (stat) {
+ bitArray |= (1<<bit);
+ } else {
+ bitArray &= ~(1<<bit);
+ }
+ return true;
+}
+
+bool PPort::registerBit(const void * ID,int bit) {
+ TEST_VALIDITY;
+ if (assignedBit[bit] || currentPort==NULL) {
+ return false;
+ }
+ assignedBit[bit]=ID;
+ return true;
+}
+
+bool PPort::unregisterBit(const void * ID,int bit) {
+ TEST_VALIDITY;
+ if (assignedBit[bit] != ID) {
+ return false;
+ }
+ assignedBit[bit]=NULL;
+ return true;
+}
+
+bool PPort::isRegisterBit(const void * ID,int bit) const {
+ TEST_VALIDITY;
+ return (assignedBit[bit] == ID);
+}
diff --git a/kstars/kstars/indi/webcam/PPort.h b/kstars/kstars/indi/webcam/PPort.h
new file mode 100644
index 00000000..c095a6e7
--- /dev/null
+++ b/kstars/kstars/indi/webcam/PPort.h
@@ -0,0 +1,75 @@
+/*
+ Copyright (C) 2004 by Jasem Mutlaq
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef _PPort_hpp_
+#define _PPort_hpp_
+
+class port_t;
+
+/** To access and share the parallel port
+ between severa objects. */
+class PPort {
+public:
+ PPort();
+ PPort(int ioPort);
+ /** set the ioport associated to the // port.
+ \return true if the binding was possible
+ */
+ bool setPort(int ioPort);
+ /** set a data bit of the // port.
+ \return false if IO port not set, or bit not registered by ID.
+ \param ID the identifier used to register the bit
+ \param stat the stat wanted for the given bit
+ \param bit the bit to set. They are numbered from 0 to 7.
+
+ */
+ bool setBit(const void * ID,int bit,bool stat);
+ /** register a bit for object ID.
+ \param ID the identifier used to register the bit it should be the 'this' pointer.
+ \param bit the bit of the // port to register
+ \return false if the bit is allready register with an
+ other ID, or if the // port is not initialised.
+ */
+ bool registerBit(const void * ID,int bit);
+ /** release a bit.
+ \param ID the identifier used to register the bit
+ \param bit the bit to register.
+ \return false if the bit was not registered by ID or
+ if the if the // port is not initialised.
+ */
+ bool unregisterBit(const void * ID,int bit);
+
+ /** test if a bit is registerd.
+ \param ID the identifier used to register the bit
+ \param bit the bit to test.
+ \return false if the bit was not registered by ID or
+ if the if the // port is not initialised.
+ */
+ bool isRegisterBit(const void * ID,int bit) const;
+
+ /** set the bits off the // port according to previous call to setBit().
+ */
+ bool commit();
+private:
+ void reset();
+ unsigned char bitArray;
+ const void * assignedBit[8];
+ port_t * currentPort;
+};
+#endif
diff --git a/kstars/kstars/indi/webcam/ccvt.h b/kstars/kstars/indi/webcam/ccvt.h
new file mode 100644
index 00000000..c78f88a6
--- /dev/null
+++ b/kstars/kstars/indi/webcam/ccvt.h
@@ -0,0 +1,164 @@
+/* CCVT: ColourConVerT: simple library for converting colourspaces
+ Copyright (C) 2002 Nemosoft Unv.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ For questions, remarks, patches, etc. for this program, the author can be
+ reached at nemosoft@smcc.demon.nl.
+*/
+
+/*
+ $Log$
+ Revision 1.4 2005/04/29 16:51:20 mutlaqja
+ Adding initial support for Video 4 Linux 2 drivers. This mean that KStars can probably control Meade Lunar Planetary Imager (LPI). V4L2 requires a fairly recent kernel (> 2.6.9) and many drivers don't fully support it yet. It will take sometime. KStars still supports V4L1 and will continue so until V4L1 is obselete. Please test KStars video drivers if you can. Any comments welcomed.
+
+ CCMAIL: kstars-devel@kde.org
+
+ Revision 1.3 2004/06/26 23:12:03 mutlaqja
+ Hopefully this will fix compile issues on 64bit archs, and FreeBSD, among others. The assembly code is replaced with a more portable, albeit slower C implementation. I imported the videodev.h header after cleaning it for user space.
+
+ Anyone who has problems compiling this, please report the problem to kstars-devel@kde.org
+
+ I noticed one odd thing after updating my kdelibs, the LEDs don't change color when state is changed. Try that by starting any INDI device, and hit connect, if the LED turns to yellow and back to grey then it works fine, otherwise, we've got a problem.
+
+ CCMAIL: kstars-devel@kde.org
+
+ Revision 1.10 2003/10/24 16:55:18 nemosoft
+ removed erronous log messages
+
+ Revision 1.9 2002/11/03 22:46:25 nemosoft
+ Adding various RGB to RGB functions.
+ Adding proper copyright header too.
+
+ Revision 1.8 2002/04/14 01:00:27 nemosoft
+ Finishing touches: adding const, adding libs for 'show'
+*/
+
+
+#ifndef CCVT_H
+#define CCVT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Colour ConVerT: going from one colour space to another.
+ ** NOTE: the set of available functions is far from complete! **
+
+ Format descriptions:
+ 420i = "4:2:0 interlaced"
+ YYYY UU YYYY UU even lines
+ YYYY VV YYYY VV odd lines
+ U/V data is subsampled by 2 both in horizontal
+ and vertical directions, and intermixed with the Y values.
+
+ 420p = "4:2:0 planar"
+ YYYYYYYY N lines
+ UUUU N/2 lines
+ VVVV N/2 lines
+ U/V is again subsampled, but all the Ys, Us and Vs are placed
+ together in separate buffers. The buffers may be placed in
+ one piece of contiguous memory though, with Y buffer first,
+ followed by U, followed by V.
+
+ yuyv = "4:2:2 interlaced"
+ YUYV YUYV YUYV ... N lines
+ The U/V data is subsampled by 2 in horizontal direction only.
+
+ bgr24 = 3 bytes per pixel, in the order Blue Green Red (whoever came up
+ with that idea...)
+ rgb24 = 3 bytes per pixel, in the order Red Green Blue (which is sensible)
+ rgb32 = 4 bytes per pixel, in the order Red Green Blue Alpha, with
+ Alpha really being a filler byte (0)
+ bgr32 = last but not least, 4 bytes per pixel, in the order Blue Green Red
+ Alpha, Alpha again a filler byte (0)
+ */
+
+/* 4:2:0 YUV planar to RGB/BGR */
+void ccvt_420p_bgr24(int width, int height, const void *src, void *dst);
+void ccvt_420p_rgb24(int width, int height, const void *src, void *dst);
+void ccvt_420p_bgr32(int width, int height, const void *src, void *dst);
+void ccvt_420p_rgb32(int width, int height, const void *src, void *dst);
+
+/* 4:2:2 YUYV interlaced to RGB/BGR */
+void ccvt_yuyv_rgb32(int width, int height, const void *src, void *dst);
+void ccvt_yuyv_bgr32(int width, int height, const void *src, void *dst);
+
+/* 4:2:2 YUYV interlaced to 4:2:0 YUV planar */
+void ccvt_yuyv_420p(int width, int height, const void *src, void *dsty, void *dstu, void *dstv);
+
+/* RGB/BGR to 4:2:0 YUV interlaced */
+
+/* RGB/BGR to 4:2:0 YUV planar */
+void ccvt_rgb24_420p(int width, int height, const void *src, void *dsty, void *dstu, void *dstv);
+void ccvt_bgr24_420p(int width, int height, const void *src, void *dsty, void *dstu, void *dstv);
+
+/* RGB/BGR to RGB/BGR */
+void ccvt_bgr24_bgr32(int width, int height, const void *const src, void *const dst);
+void ccvt_bgr24_rgb32(int width, int height, const void *const src, void *const dst);
+void ccvt_bgr32_bgr24(int width, int height, const void *const src, void *const dst);
+void ccvt_bgr32_rgb24(int width, int height, const void *const src, void *const dst);
+void ccvt_rgb24_bgr32(int width, int height, const void *const src, void *const dst);
+void ccvt_rgb24_rgb32(int width, int height, const void *const src, void *const dst);
+void ccvt_rgb32_bgr24(int width, int height, const void *const src, void *const dst);
+void ccvt_rgb32_rgb24(int width, int height, const void *const src, void *const dst);
+
+int RGB2YUV (int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip);
+
+/*
+ * BAYER2RGB24 ROUTINE TAKEN FROM:
+ *
+ * Sonix SN9C101 based webcam basic I/F routines
+ * Copyright (C) 2004 Takafumi Mizuno <taka-qce@ls-a.jp>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT);
+
+#ifdef __cplusplus
+}
+#endif
+
+enum Options {
+ ioNoBlock=(1<<0),
+ ioUseSelect=(1<<1),
+ haveBrightness=(1<<2),
+ haveContrast=(1<<3),
+ haveHue=(1<<4),
+ haveColor=(1<<5),
+ haveWhiteness=(1<<6) };
+
+
+#endif
diff --git a/kstars/kstars/indi/webcam/ccvt_c2.c b/kstars/kstars/indi/webcam/ccvt_c2.c
new file mode 100644
index 00000000..52ed276d
--- /dev/null
+++ b/kstars/kstars/indi/webcam/ccvt_c2.c
@@ -0,0 +1,118 @@
+/*
+ * Convert an image from yuv colourspace to rgb
+ *
+ * Code by Tony Hague (C) 2001.
+ */
+
+#include "ccvt.h"
+#include "ccvt_types.h"
+
+/* by suitable definition of PIXTYPE, can do yuv to rgb or bgr, with or
+without word alignment */
+
+/* This doesn't exactly earn a prize in a programming beauty contest. */
+
+#define WHOLE_FUNC2RGB(type) \
+ const unsigned char *y1, *y2, *u, *v; \
+ PIXTYPE_##type *l1, *l2; \
+ int r, g, b, cr, cg, cb, yp, j, i; \
+ \
+ if ((width & 1) || (height & 1)) \
+ return; \
+ \
+ l1 = (PIXTYPE_##type *)dst; \
+ l2 = l1 + width; \
+ y1 = (unsigned char *)src; \
+ y2 = y1 + width; \
+ u = (unsigned char *)src + width * height; \
+ v = u + (width * height) / 4; \
+ j = height / 2; \
+ while (j--) { \
+ i = width / 2; \
+ while (i--) { \
+ /* Since U & V are valid for 4 pixels, repeat code 4 \
+ times for different Y */ \
+ cb = ((*u-128) * 454)>>8; \
+ cr = ((*v-128) * 359)>>8; \
+ cg = ((*v-128) * 183 + (*u-128) * 88)>>8; \
+ \
+ yp = *(y1++); \
+ r = yp + cr; \
+ b = yp + cb; \
+ g = yp - cg; \
+ SAT(r); \
+ SAT(g); \
+ SAT(b); \
+ l1->b = b; \
+ l1->g = g; \
+ l1->r = r; \
+ l1++; \
+ \
+ yp = *(y1++); \
+ r = yp + cr; \
+ b = yp + cb; \
+ g = yp - cg; \
+ SAT(r); \
+ SAT(g); \
+ SAT(b); \
+ l1->b = b; \
+ l1->g = g; \
+ l1->r = r; \
+ l1++; \
+ \
+ yp = *(y2++); \
+ r = yp + cr; \
+ b = yp + cb; \
+ g = yp - cg; \
+ SAT(r); \
+ SAT(g); \
+ SAT(b); \
+ l2->b = b; \
+ l2->g = g; \
+ l2->r = r; \
+ l2++; \
+ \
+ yp = *(y2++); \
+ r = yp + cr; \
+ b = yp + cb; \
+ g = yp - cg; \
+ SAT(r); \
+ SAT(g); \
+ SAT(b); \
+ l2->b = b; \
+ l2->g = g; \
+ l2->r = r; \
+ l2++; \
+ \
+ u++; \
+ v++; \
+ } \
+ y1 = y2; \
+ y2 += width; \
+ l1 = l2; \
+ l2 += width; \
+ }
+
+
+
+
+void ccvt_420p_bgr32(int width, int height, const void *src, void *dst)
+{
+ WHOLE_FUNC2RGB(bgr32)
+}
+
+void ccvt_420p_bgr24(int width, int height, const void *src, void *dst)
+{
+ WHOLE_FUNC2RGB(bgr24)
+}
+
+void ccvt_420p_rgb32(int width, int height, const void *src, void *dst)
+{
+ WHOLE_FUNC2RGB(rgb32)
+}
+
+void ccvt_420p_rgb24(int width, int height, const void *src, void *dst)
+{
+ WHOLE_FUNC2RGB(rgb24)
+}
+
diff --git a/kstars/kstars/indi/webcam/ccvt_misc.c b/kstars/kstars/indi/webcam/ccvt_misc.c
new file mode 100644
index 00000000..e774ca6d
--- /dev/null
+++ b/kstars/kstars/indi/webcam/ccvt_misc.c
@@ -0,0 +1,435 @@
+/* CCVT: ColourConVerT: simple library for converting colourspaces
+ Copyright (C) 2002 Nemosoft Unv.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ For questions, remarks, patches, etc. for this program, the author can be
+ reached at nemosoft@smcc.demon.nl.
+*/
+
+/* This file contains CCVT functions that aren't available in assembly yet
+ (or are not worth programming)
+ */
+
+/*
+ * $Log$
+ * Revision 1.2 2005/04/29 16:51:20 mutlaqja
+ * Adding initial support for Video 4 Linux 2 drivers. This mean that KStars can probably control Meade Lunar Planetary Imager (LPI). V4L2 requires a fairly recent kernel (> 2.6.9) and many drivers don't fully support it yet. It will take sometime. KStars still supports V4L1 and will continue so until V4L1 is obselete. Please test KStars video drivers if you can. Any comments welcomed.
+ *
+ * CCMAIL: kstars-devel@kde.org
+ *
+ * Revision 1.1 2004/06/26 23:12:03 mutlaqja
+ * Hopefully this will fix compile issues on 64bit archs, and FreeBSD, among others. The assembly code is replaced with a more portable, albeit slower C implementation. I imported the videodev.h header after cleaning it for user space.
+ *
+ * Anyone who has problems compiling this, please report the problem to kstars-devel@kde.org
+ *
+ * I noticed one odd thing after updating my kdelibs, the LEDs don't change color when state is changed. Try that by starting any INDI device, and hit connect, if the LED turns to yellow and back to grey then it works fine, otherwise, we've got a problem.
+ *
+ * CCMAIL: kstars-devel@kde.org
+ *
+ * Revision 1.7 2003/01/02 04:10:19 nemosoft
+ * Adding ''upside down" conversion to rgb/bgr routines
+ *
+ * Revision 1.6 2002/12/03 23:29:11 nemosoft
+ * *** empty log message ***
+ *
+ * Revision 1.5 2002/12/03 23:27:41 nemosoft
+ * fixing log messages (gcc 3.2 complaining)
+ *
+ Revision 1.4 2002/12/03 22:29:07 nemosoft
+ Fixing up FTP stuff and some video
+
+ Revision 1.3 2002/11/03 22:46:25 nemosoft
+ Adding various RGB to RGB functions.
+ Adding proper copyright header too.
+ */
+
+
+#include "ccvt.h"
+#include "ccvt_types.h"
+#include <stdlib.h>
+
+static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
+static float RGBYUV01684[256], RGBYUV03316[256];
+static float RGBYUV04187[256], RGBYUV00813[256];
+
+void InitLookupTable(void);
+
+
+/* YUYV: two Y's and one U/V */
+void ccvt_yuyv_rgb32(int width, int height, const void *src, void *dst)
+{
+ width=width; height=height; src=src; dst=dst;
+
+}
+
+
+void ccvt_yuyv_bgr32(int width, int height, const void *src, void *dst)
+{
+ const unsigned char *s;
+ PIXTYPE_bgr32 *d;
+ int l, c;
+ int r, g, b, cr, cg, cb, y1, y2;
+
+ l = height;
+ s = src;
+ d = dst;
+ while (l--) {
+ c = width >> 2;
+ while (c--) {
+ y1 = *s++;
+ cb = ((*s - 128) * 454) >> 8;
+ cg = (*s++ - 128) * 88;
+ y2 = *s++;
+ cr = ((*s - 128) * 359) >> 8;
+ cg = (cg + (*s++ - 128) * 183) >> 8;
+
+ r = y1 + cr;
+ b = y1 + cb;
+ g = y1 - cg;
+ SAT(r);
+ SAT(g);
+ SAT(b);
+ d->b = b;
+ d->g = g;
+ d->r = r;
+ d++;
+ r = y2 + cr;
+ b = y2 + cb;
+ g = y2 - cg;
+ SAT(r);
+ SAT(g);
+ SAT(b);
+ d->b = b;
+ d->g = g;
+ d->r = r;
+ d++;
+ }
+ }
+
+}
+
+void ccvt_yuyv_420p(int width, int height, const void *src, void *dsty, void *dstu, void *dstv)
+{
+ int n, l, j;
+ const unsigned char *s1, *s2;
+ unsigned char *dy, *du, *dv;
+
+ dy = (unsigned char *)dsty;
+ du = (unsigned char *)dstu;
+ dv = (unsigned char *)dstv;
+ s1 = (unsigned char *)src;
+ s2 = s1; /* keep pointer */
+ n = width * height;
+ for (; n > 0; n--) {
+ *dy = *s1;
+ dy++;
+ s1 += 2;
+ }
+
+ /* Two options here: average U/V values, or skip every second row */
+ s1 = s2; /* restore pointer */
+ s1++; /* point to U */
+ for (l = 0; l < height; l += 2) {
+ s2 = s1 + width * 2; /* odd line */
+ for (j = 0; j < width; j += 2) {
+ *du = (*s1 + *s2) / 2;
+ du++;
+ s1 += 2;
+ s2 += 2;
+ *dv = (*s1 + *s2) / 2;
+ dv++;
+ s1 += 2;
+ s2 += 2;
+ }
+ s1 = s2;
+ }
+}
+
+void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT)
+{
+ long int i;
+ unsigned char *rawpt, *scanpt;
+ long int size;
+
+ rawpt = src;
+ scanpt = dst;
+ size = WIDTH*HEIGHT;
+
+ for ( i = 0; i < size; i++ ) {
+ if ( (i/WIDTH) % 2 == 0 ) {
+ if ( (i % 2) == 0 ) {
+ /* B */
+ if ( (i > WIDTH) && ((i % WIDTH) > 0) ) {
+ *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
+ *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */
+ *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
+ *(rawpt+WIDTH)+*(rawpt-WIDTH))/4; /* G */
+ *scanpt++ = *rawpt; /* B */
+ } else {
+ /* first line or left column */
+ *scanpt++ = *(rawpt+WIDTH+1); /* R */
+ *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */
+ *scanpt++ = *rawpt; /* B */
+ }
+ } else {
+ /* (B)G */
+ if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) {
+ *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* R */
+ *scanpt++ = *rawpt; /* G */
+ *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
+ } else {
+ /* first line or right column */
+ *scanpt++ = *(rawpt+WIDTH); /* R */
+ *scanpt++ = *rawpt; /* G */
+ *scanpt++ = *(rawpt-1); /* B */
+ }
+ }
+ } else {
+ if ( (i % 2) == 0 ) {
+ /* G(R) */
+ if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) {
+ *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
+ *scanpt++ = *rawpt; /* G */
+ *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* B */
+ } else {
+ /* bottom line or left column */
+ *scanpt++ = *(rawpt+1); /* R */
+ *scanpt++ = *rawpt; /* G */
+ *scanpt++ = *(rawpt-WIDTH); /* B */
+ }
+ } else {
+ /* R */
+ if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) {
+ *scanpt++ = *rawpt; /* R */
+ *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
+ *(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
+ *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
+ *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* B */
+ } else {
+ /* bottom line or right column */
+ *scanpt++ = *rawpt; /* R */
+ *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */
+ *scanpt++ = *(rawpt-WIDTH-1); /* B */
+ }
+ }
+ }
+ rawpt++;
+ }
+
+}
+
+/************************************************************************
+ *
+ * int RGB2YUV (int x_dim, int y_dim, void *bmp, YUV *yuv)
+ *
+ * Purpose : It takes a 24-bit RGB bitmap and convert it into
+ * YUV (4:2:0) format
+ *
+ * Input : x_dim the x dimension of the bitmap
+ * y_dim the y dimension of the bitmap
+ * bmp pointer to the buffer of the bitmap
+ * yuv pointer to the YUV structure
+ *
+ * Output : 0 OK
+ * 1 wrong dimension
+ * 2 memory allocation error
+ *
+ * Side Effect :
+ * None
+ *
+ * Date : 09/28/2000
+ *
+ * Contacts:
+ *
+ * Adam Li
+ *
+ * DivX Advance Research Center <darc@projectmayo.com>
+ *
+ ************************************************************************/
+
+int RGB2YUV (int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip)
+{
+ static int init_done = 0;
+
+ long i, j, size;
+ unsigned char *r, *g, *b;
+ unsigned char *y, *u, *v;
+ unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;
+ unsigned char *y_buffer, *u_buffer, *v_buffer;
+ unsigned char *sub_u_buf, *sub_v_buf;
+
+ if (init_done == 0)
+ {
+ InitLookupTable();
+ init_done = 1;
+ }
+
+ /* check to see if x_dim and y_dim are divisible by 2*/
+ if ((x_dim % 2) || (y_dim % 2)) return 1;
+ size = x_dim * y_dim;
+
+ /* allocate memory*/
+ y_buffer = (unsigned char *)y_out;
+ sub_u_buf = (unsigned char *)u_out;
+ sub_v_buf = (unsigned char *)v_out;
+ u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
+ v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
+ if (!(u_buffer && v_buffer))
+ {
+ if (u_buffer) free(u_buffer);
+ if (v_buffer) free(v_buffer);
+ return 2;
+ }
+
+ b = (unsigned char *)bmp;
+ y = y_buffer;
+ u = u_buffer;
+ v = v_buffer;
+
+ /* convert RGB to YUV*/
+ if (!flip) {
+ for (j = 0; j < y_dim; j ++)
+ {
+ y = y_buffer + (y_dim - j - 1) * x_dim;
+ u = u_buffer + (y_dim - j - 1) * x_dim;
+ v = v_buffer + (y_dim - j - 1) * x_dim;
+
+ for (i = 0; i < x_dim; i ++) {
+ g = b + 1;
+ r = b + 2;
+ *y = (unsigned char)( RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
+ *u = (unsigned char)(- RGBYUV01684[*r] - RGBYUV03316[*g] + (*b)/2 + 128);
+ *v = (unsigned char)( (*r)/2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
+ b += 3;
+ y ++;
+ u ++;
+ v ++;
+ }
+ }
+ } else {
+ for (i = 0; i < size; i++)
+ {
+ g = b + 1;
+ r = b + 2;
+ *y = (unsigned char)( RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
+ *u = (unsigned char)(- RGBYUV01684[*r] - RGBYUV03316[*g] + (*b)/2 + 128);
+ *v = (unsigned char)( (*r)/2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
+ b += 3;
+ y ++;
+ u ++;
+ v ++;
+ }
+ }
+
+ /* subsample UV*/
+ for (j = 0; j < y_dim/2; j ++)
+ {
+ psu = sub_u_buf + j * x_dim / 2;
+ psv = sub_v_buf + j * x_dim / 2;
+ pu1 = u_buffer + 2 * j * x_dim;
+ pu2 = u_buffer + (2 * j + 1) * x_dim;
+ pv1 = v_buffer + 2 * j * x_dim;
+ pv2 = v_buffer + (2 * j + 1) * x_dim;
+ for (i = 0; i < x_dim/2; i ++)
+ {
+ *psu = (*pu1 + *(pu1+1) + *pu2 + *(pu2+1)) / 4;
+ *psv = (*pv1 + *(pv1+1) + *pv2 + *(pv2+1)) / 4;
+ psu ++;
+ psv ++;
+ pu1 += 2;
+ pu2 += 2;
+ pv1 += 2;
+ pv2 += 2;
+ }
+ }
+
+ free(u_buffer);
+ free(v_buffer);
+
+ return 0;
+}
+
+
+void InitLookupTable()
+{
+ int i;
+
+ for (i = 0; i < 256; i++) RGBYUV02990[i] = (float)0.2990 * i;
+ for (i = 0; i < 256; i++) RGBYUV05870[i] = (float)0.5870 * i;
+ for (i = 0; i < 256; i++) RGBYUV01140[i] = (float)0.1140 * i;
+ for (i = 0; i < 256; i++) RGBYUV01684[i] = (float)0.1684 * i;
+ for (i = 0; i < 256; i++) RGBYUV03316[i] = (float)0.3316 * i;
+ for (i = 0; i < 256; i++) RGBYUV04187[i] = (float)0.4187 * i;
+ for (i = 0; i < 256; i++) RGBYUV00813[i] = (float)0.0813 * i;
+}
+
+
+/* RGB/BGR to RGB/BGR */
+
+#define RGBBGR_BODY24(TIN, TOUT) \
+void ccvt_ ## TIN ## _ ## TOUT (int width, int height, const void *const src, void *dst) \
+{ \
+ const PIXTYPE_ ## TIN *in = src; \
+ PIXTYPE_ ## TOUT *out = dst; \
+ int l, c, stride = 0; \
+ \
+ stride = width; \
+ out += ((height - 1) * width); \
+ stride *= 2; \
+ for (l = 0; l < height; l++) { \
+ for (c = 0; c < width; c++) { \
+ out->r = in->r; \
+ out->g = in->g; \
+ out->b = in->b; \
+ in++; \
+ out++; \
+ } \
+ out -= stride; \
+ } \
+}
+
+#define RGBBGR_BODY32(TIN, TOUT) \
+void ccvt_ ## TIN ## _ ## TOUT (int width, int height, const void *const src, void *dst) \
+{ \
+ const PIXTYPE_ ## TIN *in = src; \
+ PIXTYPE_ ## TOUT *out = dst; \
+ int l, c, stride = 0; \
+ \
+ stride = width;\
+ out += ((height - 1) * width); \
+ stride *= 2; \
+ for (l = 0; l < height; l++) { \
+ for (c = 0; c < width; c++) { \
+ out->r = in->r; \
+ out->g = in->g; \
+ out->b = in->b; \
+ out->z = 0; \
+ in++; \
+ out++; \
+ } \
+ out -= stride; \
+ } \
+}
+
+RGBBGR_BODY32(bgr24, bgr32)
+RGBBGR_BODY32(bgr24, rgb32)
+RGBBGR_BODY32(rgb24, bgr32)
+RGBBGR_BODY32(rgb24, rgb32)
+
+RGBBGR_BODY24(bgr32, bgr24)
+RGBBGR_BODY24(bgr32, rgb24)
+RGBBGR_BODY24(rgb32, bgr24)
+RGBBGR_BODY24(rgb32, rgb24)
diff --git a/kstars/kstars/indi/webcam/ccvt_types.h b/kstars/kstars/indi/webcam/ccvt_types.h
new file mode 100644
index 00000000..8e40f9fc
--- /dev/null
+++ b/kstars/kstars/indi/webcam/ccvt_types.h
@@ -0,0 +1,60 @@
+/* CCVT: ColourConVerT: simple library for converting colourspaces
+ Copyright (C) 2002 Nemosoft Unv.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ For questions, remarks, patches, etc. for this program, the author can be
+ reached at nemosoft@smcc.demon.nl.
+*/
+
+#ifndef CCVT_TYPES_H
+#define CCVT_TYPES_H
+
+typedef struct
+{
+ unsigned char b;
+ unsigned char g;
+ unsigned char r;
+ unsigned char z;
+} PIXTYPE_bgr32;
+
+typedef struct
+{
+ unsigned char b;
+ unsigned char g;
+ unsigned char r;
+} PIXTYPE_bgr24;
+
+typedef struct
+{
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+ unsigned char z;
+} PIXTYPE_rgb32;
+
+typedef struct
+{
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+} PIXTYPE_rgb24;
+
+#define SAT(c) \
+ if (c & (~255)) { if (c < 0) c = 0; else c = 255; }
+
+
+
+#endif
diff --git a/kstars/kstars/indi/webcam/port.cpp b/kstars/kstars/indi/webcam/port.cpp
new file mode 100644
index 00000000..fce53a18
--- /dev/null
+++ b/kstars/kstars/indi/webcam/port.cpp
@@ -0,0 +1,199 @@
+/* libcqcam - shared Color Quickcam routines
+ * Copyright (C) 1996-1998 by Patrick Reynolds
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// I/O ports wrapper code
+// This file might need tweaking if you're trying to port my code to other
+// x86 Unix platforms. Code is already available for Linux, FreeBSD, and
+// QNX; see the Makefile.
+//
+// QNX code by: Anders Arpteg <aa11ac@hik.se>
+// FreeBSD code by: Patrick Reynolds <reynolds@cs.duke.edu> and Charles
+// Henrich <henrich@msu.edu>
+
+
+//#include "config.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+#ifdef LOCKING
+#include <fcntl.h>
+#include <sys/stat.h>
+#endif /* LOCKING */
+
+#ifdef __linux__
+ #if defined(arm) || defined(__hppa__) || defined(__sparc__) || defined(__ppc__) || defined(__powerpc__) || defined(__s390__) || defined(__s390x__) || defined(__mips__) || defined(__mc68000__)
+ #include <fcntl.h>
+ #else
+ #include <sys/io.h>
+ #endif /* arm */
+#elif defined(QNX)
+#include <conio.h>
+#elif defined(__FreeBSD__)
+#include <sys/types.h>
+#include <machine/cpufunc.h>
+#elif defined(BSDI)
+#include <machine/inline.h>
+#elif defined(OPENBSD)
+#include <machine/pio.h>
+#elif defined(LYNX)
+#include "lynx-io.h"
+#elif defined(SOLARIS)
+#include "solaris-io.h"
+#else
+#error Please define a platform in the Makefile
+#endif /* which OS */
+
+#include "port.h"
+
+port_t::port_t(int iport) {
+ port = -1;
+
+#ifdef LOCKING
+ if (lock(iport) == -1) {
+#ifdef DEBUG
+ fprintf(stderr, "port 0x%x already locked\n", iport);
+#endif /* DEBUG */
+ return;
+ }
+#endif /* LOCKING */
+
+#ifdef LINUX
+#if defined(arm) || defined(__hppa__) || defined(__sparc__) || defined(__ppc__) || defined(__powerpc__) || defined(__s390__) || defined(__s390x__) || defined(__mips__) || defined(__mc68000__)
+ if ((devport = open("/dev/port", O_RDWR)) < 0) {
+ perror("open /dev/port");
+ return;
+ }
+#else
+ if (ioperm(iport, 3, 1) == -1) {
+ perror("ioperm()");
+ return;
+ }
+#endif /* arm */
+#elif defined(FREEBSD)
+ if ((devio = fopen("/dev/io", "r+")) == NULL) {
+ perror("fopen /dev/io");
+ return;
+ }
+#elif defined(OPENBSD)
+ if (i386_iopl(1) == -1) {
+ perror("i386_iopl");
+ return;
+ }
+#elif defined(LYNX)
+ if (io_access() < 0) {
+ perror("io_access");
+ return;
+ }
+#elif defined(SOLARIS)
+ if (openiop()) {
+ perror("openiop");
+ return;
+ }
+#endif /* which OS */
+
+ port = iport;
+ port1 = port + 1;
+ port2 = port + 2;
+ control_reg = read_control();
+}
+
+port_t::~port_t(void) {
+#ifdef LOCKING
+ unlock(port);
+#endif /* LOCKING */
+#ifdef LINUX
+#if defined(arm) || defined(__hppa__) || defined(__sparc__) || defined(__ppc__) || defined(__powerpc__) || defined(__s390__) || defined(__s390x__) || defined(__mips__) || defined(__mc68000__)
+ if (devport >= 0)
+ close(devport);
+#else
+ if (port > 0 && geteuid() == 0)
+ if (ioperm(port, 3, 0) != 0) // drop port permissions -- still must
+ // be root
+ perror("ioperm()");
+#endif /* arm */
+#elif defined(FREEBSD)
+ if (devio != NULL)
+ fclose(devio);
+#elif defined(SOLARIS)
+ close(iopfd);
+#endif /* which OS */
+}
+
+#ifdef LOCKING
+int port_t::lock(int portnum) {
+ char lockfile[80];
+ sprintf(lockfile, "/tmp/LOCK.qcam.0x%x", portnum);
+ while ((lock_fd = open(lockfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == -1) {
+ if (errno != EEXIST) {
+ perror(lockfile);
+ return -1;
+ }
+ struct stat stat_buf;
+ if (lstat(lockfile, &stat_buf) < 0) continue;
+ if (S_ISLNK(stat_buf.st_mode) || stat_buf.st_uid != 0) {
+ if (unlink(lockfile)) {
+ if (errno == ENOENT) continue;
+ if (errno != EISDIR || (rmdir(lockfile) && errno != ENOENT)) {
+ /* known problem: if lockfile exists and is a non-empty
+ directory, we give up instead of doing an rm-r of it */
+ perror(lockfile);
+ return -1;
+ }
+ }
+ continue;
+ }
+ lock_fd = open(lockfile, O_WRONLY, 0600);
+ if (lock_fd == -1) {
+ perror(lockfile);
+ return -1;
+ }
+ break;
+ }
+
+ static struct flock lock_info;
+ lock_info.l_type = F_WRLCK;
+#ifdef LOCK_FAIL
+ if (fcntl(lock_fd, F_SETLK, &lock_info) != 0) {
+#else
+ if (fcntl(lock_fd, F_SETLKW, &lock_info) != 0) {
+#endif /* LOCK_FAIL */
+ if (errno != EAGAIN)
+ perror("fcntl");
+ return -1;
+ }
+ chown(lockfile, getuid(), getgid());
+#ifdef DEBUG
+ fprintf(stderr, "Locked port 0x%x\n", portnum);
+#endif /* DEBUG */
+ return 0;
+}
+
+void port_t::unlock(int portnum) {
+ if (portnum == -1)
+ return;
+ close(lock_fd); // this clears the lock
+ char lockfile[80];
+ sprintf(lockfile, "/tmp/LOCK.qcam.0x%x", portnum);
+ if (unlink(lockfile)) perror(lockfile);
+#ifdef DEBUG
+ fprintf(stderr, "Unlocked port 0x%x\n", portnum);
+#endif /* DEBUG */
+}
+#endif /* LOCKING */
diff --git a/kstars/kstars/indi/webcam/port.h b/kstars/kstars/indi/webcam/port.h
new file mode 100644
index 00000000..c5896858
--- /dev/null
+++ b/kstars/kstars/indi/webcam/port.h
@@ -0,0 +1,122 @@
+/* libcqcam - shared Color Quickcam routines
+ * Copyright (C) 1996-1998 by Patrick Reynolds
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// I/O ports wrapper definitions and prototypes
+// This file might need tweaking if you're trying to port my code to other
+// x86 Unix platforms. Code is already available for Linux, FreeBSD, and
+// QNX; see the Makefile.
+//
+// QNX code by: Anders Arpteg <aa11ac@hik.se>
+// FreeBSD code by: Patrick Reynolds <reynolds@cs.duke.edu> and Charles
+// Henrich <henrich@msu.edu>
+// Inlining implemented by: Philip Blundell <philip.blundell@pobox.com>
+
+#ifndef PORT_H
+#define PORT_H
+
+//#include "config.h"
+
+#include <unistd.h>
+
+#ifdef __linux__
+ #if !defined(arm) && !defined(__hppa__) && !defined(__sparc__) && !defined(__ppc__) && !defined(__powerpc__) && !defined(__s390__) && !defined(__s390x__) && !defined(__mips__) && !defined(__mc68000__)
+ #include <sys/io.h>
+ #endif /* !arm */
+#elif defined(QNX)
+#include <conio.h>
+#elif defined(__FreeBSD__)
+#include <machine/cpufunc.h>
+#include <stdio.h>
+#elif defined(BSDI)
+#include <machine/inline.h>
+#elif defined(OPENBSD)
+#include <machine/pio.h>
+#elif defined(LYNX)
+#include "lynx-io.h"
+#elif defined(SOLARIS)
+#include "solaris-io.h"
+#else
+#error Please define a platform in the Makefile
+#endif
+
+#if defined(arm) || defined(__hppa__) || defined(__sparc__) || defined(__ppc__) || defined(__powerpc__) || defined(__s390__) || defined(__s390x__) || defined(__mips__) || defined(__mc68000__)
+static char ports_temp;
+
+#ifdef inb
+#undef inb
+#endif /* inb */
+#define inb(port) \
+ lseek(devport, port, SEEK_SET), \
+ read(devport, &ports_temp, 1), \
+ ports_temp
+
+#ifdef outb
+#undef outb
+#endif /* inb */
+#define outb(data, port) \
+ lseek(devport, port, SEEK_SET); \
+ ports_temp = data; \
+ write(devport, &ports_temp, 1);
+
+#endif /* arm, hppa */
+
+class port_t {
+public:
+ port_t(int iport);
+ ~port_t(void);
+
+ inline int read_data(void) { return inb(port); }
+ inline int read_status(void) { return inb(port1); }
+ inline int read_control(void) { return inb(port2); }
+
+#if defined(LINUX) || defined(LYNX)
+ inline void write_data(int data) { outb(data, port); }
+ inline void write_control(int data) { outb(control_reg = data, port2); }
+ inline void setbit_control(int data) { outb(control_reg |= data, port2); }
+ inline void clearbit_control(int data) { outb(control_reg &= ~data, port2); }
+#else // Solaris, QNX, and *BSD use (port, data) instead
+ inline void write_data(int data) { outb(port, data); }
+ inline void write_control(int data) { outb(port2, control_reg = data); }
+ inline void setbit_control(int data) { outb(port2, control_reg |= data); }
+ inline void clearbit_control(int data) { outb(port2, control_reg &= ~data); }
+#endif
+
+ inline int get_port() { return port; }
+ inline operator bool () const { return port != -1; }
+
+private:
+ int port; // number of the base port
+ int port1; // port+1, precalculated for speed
+ int port2; // port+2, precalculated for speed
+ int control_reg; // current contents of the control register
+#ifdef LOCKING
+ int lock_fd;
+ int lock(int portnum);
+ void unlock(int portnum);
+#endif
+
+#ifdef FREEBSD
+ FILE *devio;
+#endif
+#if defined(__linux__) && (defined(arm) || defined(__hppa__) || defined(__sparc__) || defined(__ppc__) || defined(__powerpc__) || defined(__s390__) || defined(__s390x__) || defined(__mips__) || defined(__mc68000__))
+ int devport;
+#endif
+};
+
+#endif
diff --git a/kstars/kstars/indi/webcam/pwc-ioctl.h b/kstars/kstars/indi/webcam/pwc-ioctl.h
new file mode 100644
index 00000000..9b650298
--- /dev/null
+++ b/kstars/kstars/indi/webcam/pwc-ioctl.h
@@ -0,0 +1,176 @@
+#ifndef PWC_IOCTL_H
+#define PWC_IOCTL_H
+
+/* (C) 2001-2002 Nemosoft Unv. webcam@smcc.demon.nl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/* This is pwc-ioctl.h belonging to PWC 8.6 */
+
+/*
+ Changes
+ 2001/08/03 Alvarado Added ioctl constants to access methods for
+ changing white balance and red/blue gains
+ */
+
+/* These are private ioctl() commands, specific for the Philips webcams.
+ They contain functions not found in other webcams, and settings not
+ specified in the Video4Linux API.
+
+ The #define names are built up like follows:
+ VIDIOC VIDeo IOCtl prefix
+ PWC Philps WebCam
+ G optional: Get
+ S optional: Set
+ ... the function
+ */
+
+
+
+
+/* The frame rate is encoded in the video_window.flags parameter using
+ the upper 16 bits, since some flags are defined nowadays. The following
+ defines provide a mask and shift to filter out this value.
+
+ In 'Snapshot' mode the camera freezes its automatic exposure and colour
+ balance controls.
+ */
+#define PWC_FPS_SHIFT 16
+#define PWC_FPS_MASK 0x00FF0000
+#define PWC_FPS_FRMASK 0x003F0000
+#define PWC_FPS_SNAPSHOT 0x00400000
+
+
+
+struct pwc_probe
+{
+ char name[32];
+ int type;
+};
+
+
+/* pwc_whitebalance.mode values */
+#define PWC_WB_INDOOR 0
+#define PWC_WB_OUTDOOR 1
+#define PWC_WB_FL 2
+#define PWC_WB_MANUAL 3
+#define PWC_WB_AUTO 4
+
+/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
+ Set mode to one of the PWC_WB_* values above.
+ *red and *blue are the respective gains of these colour components inside
+ the camera; range 0..65535
+ When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
+ otherwise undefined.
+ 'read_red' and 'read_blue' are read-only.
+*/
+
+struct pwc_whitebalance
+{
+ int mode;
+ int manual_red, manual_blue; /* R/W */
+ int read_red, read_blue; /* R/O */
+};
+
+/*
+ 'control_speed' and 'control_delay' are used in automatic whitebalance mode,
+ and tell the camera how fast it should react to changes in lighting, and
+ with how much delay. Valid values are 0..65535.
+*/
+struct pwc_wb_speed
+{
+ int control_speed;
+ int control_delay;
+
+};
+
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+ int led_on; /* Led on-time; range = 0..25000 */
+ int led_off; /* Led off-time; range = 0..25000 */
+};
+
+
+
+ /* Restore user settings */
+#define VIDIOCPWCRUSER _IO('v', 192)
+ /* Save user settings */
+#define VIDIOCPWCSUSER _IO('v', 193)
+ /* Restore factory settings */
+#define VIDIOCPWCFACTORY _IO('v', 194)
+
+ /* You can manipulate the compression factor. A compression preference of 0
+ means use uncompressed modes when available; 1 is low compression, 2 is
+ medium and 3 is high compression preferred. Of course, the higher the
+ compression, the lower the bandwidth used but more chance of artefacts
+ in the image. The driver automatically chooses a higher compression when
+ the preferred mode is not available.
+ */
+ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
+#define VIDIOCPWCSCQUAL _IOW('v', 195, int)
+ /* Get preferred compression quality */
+#define VIDIOCPWCGCQUAL _IOR('v', 195, int)
+
+
+ /* This is a probe function; since so many devices are supported, it
+ becomes difficult to include all the names in programs that want to
+ check for the enhanced Philips stuff. So in stead, try this PROBE;
+ it returns a structure with the original name, and the corresponding
+ Philips type.
+ To use, fill the structure with zeroes, call PROBE and if that succeeds,
+ compare the name with that returned from VIDIOCGCAP; they should be the
+ same. If so, you can be assured it is a Philips (OEM) cam and the type
+ is valid.
+ */
+#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe)
+
+ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
+#define VIDIOCPWCSAGC _IOW('v', 200, int)
+ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCGAGC _IOR('v', 200, int)
+ /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCSSHUTTER _IOW('v', 201, int)
+
+ /* Color compensation (Auto White Balance) */
+#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance)
+#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance)
+
+ /* Auto WB speed */
+#define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed)
+#define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed)
+
+ /* LEDs on/off/blink; int range 0..65535 */
+#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds)
+#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds)
+
+ /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
+#define VIDIOCPWCSCONTOUR _IOW('v', 206, int)
+#define VIDIOCPWCGCONTOUR _IOR('v', 206, int)
+
+ /* Backlight compensation; 0 = off, otherwise on */
+#define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int)
+#define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int)
+
+ /* Flickerless mode; = 0 off, otherwise on */
+#define VIDIOCPWCSFLICKER _IOW('v', 208, int)
+#define VIDIOCPWCGFLICKER _IOR('v', 208, int)
+
+ /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
+#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int)
+#define VIDIOCPWCGDYNNOISE _IOR('v', 209, int)
+
+#endif
diff --git a/kstars/kstars/indi/webcam/v4l1_base.cpp b/kstars/kstars/indi/webcam/v4l1_base.cpp
new file mode 100644
index 00000000..12007870
--- /dev/null
+++ b/kstars/kstars/indi/webcam/v4l1_base.cpp
@@ -0,0 +1,564 @@
+/*
+ Copyright (C) 2005 by Jasem Mutlaq
+
+ Some code based on qastrocam
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include <iostream>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <string.h>
+
+#include "ccvt.h"
+#include "v4l1_base.h"
+#include "../eventloop.h"
+#include "../indidevapi.h"
+
+#define ERRMSGSIZ 1024
+
+using namespace std;
+
+V4L1_Base::V4L1_Base()
+{
+ frameRate=10;
+ fd=-1;
+ //usingTimer = false;
+
+ //frameUpdate = true;
+ //selectCallBackID = -1;
+ //timerCallBackID = -1;
+
+ YBuf = NULL;
+ UBuf = NULL;
+ VBuf = NULL;
+ colorBuffer= NULL;
+ buffer_start=NULL;
+
+}
+
+V4L1_Base::~V4L1_Base()
+{
+
+ delete (YBuf);
+ delete (UBuf);
+ delete (VBuf);
+ delete (colorBuffer);
+
+}
+
+int V4L1_Base::connectCam(const char * devpath, char *errmsg)
+{
+ options= (haveBrightness|haveContrast|haveHue|haveColor|haveWhiteness);
+
+ buffer_start=NULL;
+ frameRate=10;
+ fd=-1;
+ //usingTimer = false;
+
+ //frameUpdate = true;
+ //selectCallBackID = -1;
+ //timerCallBackID = -1;
+
+ cerr << "In connect Cam with device " << devpath << endl;
+ if (-1 == (fd=open(devpath, O_RDONLY | O_NONBLOCK, 0)))
+ {
+ strncpy(errmsg, strerror(errno), ERRMSGSIZ);
+ cerr << strerror(errno);
+ return -1;
+ }
+
+ cerr << "Device opened" << endl;
+
+ if (fd != -1)
+ {
+ if (-1 == ioctl(fd,VIDIOCGCAP,&capability))
+ {
+ cerr << "Error: ioctl (VIDIOCGCAP)" << endl;
+ strncpy(errmsg, "ioctl (VIDIOCGCAP)", ERRMSGSIZ);
+ return -1;
+ }
+ if (-1 == ioctl (fd, VIDIOCGWIN, &window))
+ {
+ cerr << "Error ioctl (VIDIOCGWIN)" << endl;
+ strncpy(errmsg, "ioctl (VIDIOCGWIN)", ERRMSGSIZ);
+ return -1;
+ }
+ if (-1 == ioctl (fd, VIDIOCGPICT, &picture_format))
+ {
+ cerr << "Error: ioctl (VIDIOCGPICT)" << endl;
+ strncpy(errmsg, "ioctl (VIDIOCGPICT)", ERRMSGSIZ);
+ return -1;
+ }
+
+ init(0);
+ }
+
+ cerr << "initial size w:" << window.width << " -- h: " << window.height << endl;
+
+ /*if (options & ioUseSelect)
+ {
+ selectCallBackID = addCallback(fd, V4L1_Base::staticUpdateFrame, this);
+ cerr << "Using select to wait new frames." << endl;
+ } else
+ {
+ usingTimer = true;
+ timerCallBackID = addTimer(1000/frameRate, V4L1_Base::staticCallFrame, this);
+ cerr << "Using timer to wait new frames.\n";
+ }
+ */
+
+ mmapInit();
+ //mmapCapture();
+
+ cerr << "All successful, returning\n";
+ return fd;
+}
+
+void V4L1_Base::disconnectCam()
+{
+
+
+ delete YBuf;
+ delete UBuf;
+ delete VBuf;
+ YBuf = UBuf = VBuf = NULL;
+
+ if (selectCallBackID != -1)
+ rmCallback(selectCallBackID);
+
+ //if (usingTimer && timerCallBackID != -1)
+ //rmTimer(timerCallBackID);
+
+ if (munmap (buffer_start, mmap_buffer.size) < 0)
+ fprintf(stderr, "munmap: %s\n", strerror(errno));
+
+ if (close(fd) < 0)
+ fprintf(stderr, "close(fd): %s\n", strerror(errno));
+
+ fprintf(stderr, "Disconnect cam\n");
+}
+
+//void V4L1_Base::staticCallFrame(void *p)
+//{
+// ((V4L1_Base *) p)->updateFrame(0, NULL);
+//}
+
+//void V4L1_Base::staticUpdateFrame(int /*d*/, void *p)
+//{
+// ((V4L1_Base *) p)->updateFrame(0, NULL);
+//}
+
+void V4L1_Base::newFrame()
+{
+ switch (picture_format.palette)
+ {
+ case VIDEO_PALETTE_GREY:
+ memcpy(YBuf,mmapFrame(),window.width * window.height);
+ break;
+ case VIDEO_PALETTE_YUV420P:
+ memcpy(YBuf,mmapFrame(), window.width * window.height);
+ memcpy(UBuf,
+ mmapFrame()+ window.width * window.height,
+ (window.width/2) * (window.height/2));
+ memcpy(VBuf,
+ mmapFrame()+ window.width * window.height+(window.width/2) * (window.height/2),
+ (window.width/2) * (window.height/2));
+ break;
+ case VIDEO_PALETTE_YUYV:
+ ccvt_yuyv_420p(window.width,window.height,
+ mmapFrame(),
+ YBuf,
+ UBuf,
+ VBuf);
+ break;
+
+ case VIDEO_PALETTE_RGB24:
+ RGB2YUV(window.width, window.height, mmapFrame(), YBuf, UBuf, VBuf, 0);
+ break;
+
+ default:
+ cerr << "invalid palette " <<picture_format.palette << endl;
+ exit(1);
+ }
+
+
+ if (callback)
+ (*callback)(uptr);
+
+}
+
+void V4L1_Base::updateFrame(int /*d*/, void * p)
+{
+
+ ( (V4L1_Base *) (p))->newFrame();
+
+}
+
+int V4L1_Base::start_capturing(char * /*errmsg*/)
+{
+
+ mmapCapture();
+ mmapSync();
+
+ selectCallBackID = IEAddCallback(fd, updateFrame, this);
+ //newFrame();
+ return 0;
+}
+
+int V4L1_Base::stop_capturing(char * /*errmsg*/)
+{
+
+ IERmCallback(selectCallBackID);
+ selectCallBackID = -1;
+ return 0;
+}
+
+int V4L1_Base::getWidth()
+{
+ return window.width;
+}
+
+int V4L1_Base::getHeight()
+{
+ return window.height;
+}
+
+void V4L1_Base::setFPS(int fps)
+{
+ frameRate = fps;
+}
+
+int V4L1_Base::getFPS()
+{
+ return frameRate;
+}
+
+char * V4L1_Base::getDeviceName()
+{
+ return capability.name;
+}
+
+void V4L1_Base::init(int preferedPalette)
+ {
+
+ if (preferedPalette)
+ {
+ picture_format.palette=preferedPalette;
+ if (0 == ioctl(fd, VIDIOCSPICT, &picture_format))
+ cerr << "found preferedPalette " << preferedPalette << endl;
+ else
+ {
+ preferedPalette=0;
+ cerr << "preferedPalette " << preferedPalette << " invalid, trying to find one." << endl;
+ }
+ }
+
+ if (preferedPalette == 0)
+ {
+ do {
+ /* trying VIDEO_PALETTE_YUV420P (Planar) */
+ picture_format.palette=VIDEO_PALETTE_YUV420P;
+ if (0 == ioctl(fd, VIDIOCSPICT, &picture_format)) {
+ cerr << "found palette VIDEO_PALETTE_YUV420P" << endl;
+ break;
+ }
+ cerr << "VIDEO_PALETTE_YUV420P not supported." << endl;
+ /* trying VIDEO_PALETTE_YUV420 (interlaced) */
+ picture_format.palette=VIDEO_PALETTE_YUV420;
+ if ( 0== ioctl(fd, VIDIOCSPICT, &picture_format)) {
+ cerr << "found palette VIDEO_PALETTE_YUV420" << endl;
+ break;
+ }
+ cerr << "VIDEO_PALETTE_YUV420 not supported." << endl;
+ /* trying VIDEO_PALETTE_RGB24 */
+ picture_format.palette=VIDEO_PALETTE_RGB24;
+ if ( 0== ioctl(fd, VIDIOCSPICT, &picture_format)) {
+ cerr << "found palette VIDEO_PALETTE_RGB24" << endl;
+ break;
+ }
+ cerr << "VIDEO_PALETTE_RGB24 not supported." << endl;
+ /* trying VIDEO_PALETTE_GREY */
+ picture_format.palette=VIDEO_PALETTE_GREY;
+ if ( 0== ioctl(fd, VIDIOCSPICT, &picture_format)) {
+ cerr << "found palette VIDEO_PALETTE_GREY" << endl;
+ break;
+ }
+ cerr << "VIDEO_PALETTE_GREY not supported." << endl;
+ cerr << "could not find a supported palette." << endl;
+ exit(1);
+ } while (false);
+ }
+
+ allocBuffers();
+
+}
+
+void V4L1_Base::allocBuffers()
+{
+ delete YBuf;
+ delete UBuf;
+ delete VBuf;
+ delete colorBuffer;
+
+ YBuf= new unsigned char[window.width * window.height];
+ UBuf= new unsigned char[window.width * window.height];
+ VBuf= new unsigned char[window.width * window.height];
+ colorBuffer = new unsigned char[window.width * window.height * 4];
+}
+
+void V4L1_Base::checkSize(int & x, int & y)
+{
+ if (x >= capability.maxwidth && y >= capability.maxheight)
+ {
+ x=capability.maxwidth;
+ y=capability.maxheight;
+ }
+ else if (x>=352 && y >=288) {
+ x=352;y=288;
+ } else if (x>=320 && y >= 240) {
+ x=320;y=240;
+ } else if (x>=176 && y >=144) {
+ x=176;y=144;
+ } else if (x>=160 && y >=120 ) {
+ x=160;y=120;
+ } else
+ {
+ x=capability.minwidth;
+ y=capability.minheight;
+ }
+}
+
+void V4L1_Base::getMaxMinSize(int & xmax, int & ymax, int & xmin, int & ymin)
+{
+ xmax = capability.maxwidth;
+ ymax = capability.maxheight;
+ xmin = capability.minwidth;
+ ymin = capability.minheight;
+}
+
+bool V4L1_Base::setSize(int x, int y)
+{
+ int oldX, oldY;
+ checkSize(x,y);
+
+ oldX = window.width;
+ oldY = window.height;
+
+ window.width=x;
+ window.height=y;
+
+ cerr << "New size is x=" << window.width << " " << "y=" << window.height <<endl;
+
+ if (ioctl (fd, VIDIOCSWIN, &window))
+ {
+ cerr << "ioctl(VIDIOCSWIN)" << endl;
+ window.width=oldX;
+ window.height=oldY;
+ return false;
+ }
+ ioctl (fd, VIDIOCGWIN, &window);
+
+ allocBuffers();
+
+ return true;
+}
+
+void V4L1_Base::setContrast(int val)
+{
+ picture_format.contrast=val;
+ setPictureSettings();
+}
+
+int V4L1_Base::getContrast()
+{
+ return picture_format.contrast;
+}
+
+void V4L1_Base::setBrightness(int val)
+{
+ picture_format.brightness=val;
+ setPictureSettings();
+}
+
+int V4L1_Base::getBrightness()
+{
+ return picture_format.brightness;
+}
+
+void V4L1_Base::setColor(int val)
+{
+ picture_format.colour=val;
+ setPictureSettings();
+}
+
+int V4L1_Base::getColor()
+{
+ return picture_format.colour;
+}
+
+void V4L1_Base::setHue(int val)
+{
+ picture_format.hue=val;
+ setPictureSettings();
+}
+
+int V4L1_Base::getHue()
+{
+ return picture_format.hue;
+}
+
+void V4L1_Base::setWhiteness(int val)
+{
+ picture_format.whiteness=val;
+ setPictureSettings();
+}
+
+int V4L1_Base::getWhiteness()
+{
+ return picture_format.whiteness;
+}
+
+void V4L1_Base::setPictureSettings()
+{
+ if (ioctl(fd, VIDIOCSPICT, &picture_format) ) {
+ cerr << "setPictureSettings" << endl;
+ }
+ ioctl(fd, VIDIOCGPICT, &picture_format);
+}
+
+void V4L1_Base::getPictureSettings()
+{
+ if (ioctl(fd, VIDIOCGPICT, &picture_format) )
+ {
+ cerr << "getPictureSettings" << endl;
+ }
+}
+
+int V4L1_Base::mmapInit()
+{
+ mmap_buffer.size = 0;
+ mmap_buffer.frames = 0;
+
+ mmap_sync_buffer=-1;
+ mmap_capture_buffer=-1;
+ buffer_start=NULL;
+
+ if (ioctl(fd, VIDIOCGMBUF, &mmap_buffer)) {
+ // mmap not supported
+ return -1;
+ }
+
+ buffer_start = (unsigned char *) mmap (NULL, mmap_buffer.size, PROT_READ, MAP_SHARED, fd, 0);
+
+ if (buffer_start == MAP_FAILED)
+ {
+ cerr << "mmap" << endl;
+ mmap_buffer.size = 0;
+ mmap_buffer.frames = 0;
+ buffer_start=NULL;
+ return -1;
+ }
+
+ return 0;
+}
+
+void V4L1_Base::mmapCapture()
+{
+
+ struct video_mmap vm;
+ mmap_capture_buffer = (mmap_capture_buffer + 1) % mmap_buffer.frames;
+
+ vm.frame = mmap_capture_buffer;
+ vm.format = picture_format.palette;
+ vm.width = window.width;
+ vm.height = window.height;
+
+ if (ioctl(fd, VIDIOCMCAPTURE, &vm) < 0)
+ cerr << "Error V4L1_Base::mmapCapture" << endl;
+}
+
+void V4L1_Base::mmapSync()
+{
+ mmap_sync_buffer= (mmap_sync_buffer + 1) % mmap_buffer.frames;
+
+ if (ioctl(fd, VIDIOCSYNC, &mmap_sync_buffer) < 0)
+ cerr << "Error V4L1_Base::mmapSync()" << endl;
+}
+
+unsigned char * V4L1_Base::mmapFrame()
+{
+ return (buffer_start + mmap_buffer.offsets[mmap_sync_buffer]);
+}
+
+unsigned char * V4L1_Base::getY()
+{
+ return YBuf;
+}
+
+unsigned char * V4L1_Base::getU()
+{
+ return UBuf;
+}
+
+unsigned char * V4L1_Base::getV()
+{
+ return VBuf;
+}
+
+unsigned char * V4L1_Base::getColorBuffer()
+{
+ //cerr << "in get color buffer " << endl;
+
+ switch (picture_format.palette)
+ {
+ case VIDEO_PALETTE_YUV420P:
+ ccvt_420p_bgr32(window.width, window.height,
+ mmapFrame(), (void*)colorBuffer);
+ break;
+
+ case VIDEO_PALETTE_YUYV:
+ ccvt_yuyv_bgr32(window.width, window.height,
+ mmapFrame(), (void*)colorBuffer);
+ break;
+
+ case VIDEO_PALETTE_RGB24:
+ ccvt_rgb24_bgr32(window.width, window.height,
+ mmapFrame(), (void*)colorBuffer);
+ break;
+
+ default:
+ break;
+ }
+
+
+ return colorBuffer;
+
+}
+
+void V4L1_Base::registerCallback(WPF *fp, void *ud)
+{
+ callback = fp;
+ uptr = ud;
+}
diff --git a/kstars/kstars/indi/webcam/v4l1_base.h b/kstars/kstars/indi/webcam/v4l1_base.h
new file mode 100644
index 00000000..7a7c93f9
--- /dev/null
+++ b/kstars/kstars/indi/webcam/v4l1_base.h
@@ -0,0 +1,110 @@
+/*
+ Copyright (C) 2005 by Jasem Mutlaq
+
+ Some code based on qastrocam
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef V4L1_BASE_H
+#define V4L1_BASE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "videodev.h"
+#include "../eventloop.h"
+
+class V4L1_Base
+{
+ public:
+ V4L1_Base();
+ virtual ~V4L1_Base();
+
+ /* Connection */
+ virtual int connectCam(const char * devpath, char *errmsg);
+ virtual void disconnectCam();
+ char * getDeviceName();
+
+ /* Image settings */
+ int getBrightness();
+ int getContrast();
+ int getColor();
+ int getHue();
+ int getWhiteness();
+ void setContrast(int val);
+ void setBrightness(int val);
+ void setColor(int val);
+ void setHue(int val);
+ void setWhiteness(int val);
+
+ /* Updates */
+ static void updateFrame(int d, void * p);
+ void newFrame();
+ void setPictureSettings();
+ void getPictureSettings();
+
+ /* Image Size */
+ int getWidth();
+ int getHeight();
+ void checkSize(int & x, int & y);
+ virtual bool setSize(int x, int y);
+ virtual void getMaxMinSize(int & xmax, int & ymax, int & xmin, int & ymin);
+
+ /* Frame rate */
+ void setFPS(int fps);
+ int getFPS();
+
+ void init(int preferedPalette);
+ void allocBuffers();
+ int mmapInit();
+ void mmapCapture();
+ void mmapSync();
+
+ unsigned char * mmapFrame();
+ unsigned char * getY();
+ unsigned char * getU();
+ unsigned char * getV();
+ unsigned char * getColorBuffer();
+
+ int start_capturing(char *errmsg);
+ int stop_capturing(char *errmsg);
+ void registerCallback(WPF *fp, void *ud);
+
+ protected:
+
+ int fd;
+ WPF *callback;
+ void *uptr;
+ unsigned long options;
+
+ struct video_capability capability;
+ struct video_window window;
+ struct video_picture picture_format;
+ struct video_mbuf mmap_buffer;
+
+ unsigned char * buffer_start;
+
+ long mmap_sync_buffer;
+ long mmap_capture_buffer;
+
+ int frameRate;
+ bool streamActive;
+ int selectCallBackID;
+ unsigned char * YBuf,*UBuf,*VBuf, *colorBuffer;
+
+};
+
+#endif
diff --git a/kstars/kstars/indi/webcam/v4l1_pwc.cpp b/kstars/kstars/indi/webcam/v4l1_pwc.cpp
new file mode 100644
index 00000000..9f644885
--- /dev/null
+++ b/kstars/kstars/indi/webcam/v4l1_pwc.cpp
@@ -0,0 +1,563 @@
+/*
+ Phlips webcam driver for V4L 1
+ Copyright (C) 2005 by Jasem Mutlaq
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include <iostream>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <string.h>
+
+#include "ccvt.h"
+#include "pwc-ioctl.h"
+#include "v4l1_pwc.h"
+#include "../eventloop.h"
+
+#define ERRMSG_SIZ 1024
+
+extern int errno;
+using namespace std;
+
+V4L1_PWC::V4L1_PWC()
+{
+ frameRate=15;
+ fd=-1;
+ streamActive = true;
+
+ YBuf = NULL;
+ UBuf = NULL;
+ VBuf = NULL;
+ colorBuffer= NULL;
+ buffer_start=NULL;
+}
+
+V4L1_PWC::~V4L1_PWC()
+{
+
+}
+
+int V4L1_PWC::connectCam(const char * devpath, char *errmsg)
+{
+ options= (ioNoBlock|ioUseSelect|haveBrightness|haveContrast|haveColor);
+ struct pwc_probe probe;
+ bool IsPhilips = false;
+ frameRate=15;
+ fd=-1;
+ streamActive = true;
+ buffer_start=NULL;
+
+ if (-1 == (fd=open(devpath,
+ O_RDONLY | ((options & ioNoBlock) ? O_NONBLOCK : 0)))) {
+
+ strncpy(errmsg, strerror(errno), 1024);
+ cerr << strerror(errno);
+ return -1;
+ }
+
+ cerr << "Device opened" << endl;
+
+ if (fd != -1) {
+ if (-1 == ioctl(fd,VIDIOCGCAP,&capability)) {
+ cerr << "Error: ioctl (VIDIOCGCAP)" << endl;
+ strncpy(errmsg, "ioctl (VIDIOCGCAP)", 1024);
+ return -1;
+ }
+ if (-1 == ioctl (fd, VIDIOCGWIN, &window)) {
+ cerr << "Error: ioctl (VIDIOCGWIN)" << endl;
+ strncpy(errmsg, "ioctl (VIDIOCGWIN)", 1024);
+ return -1;
+ }
+ if (-1 == ioctl (fd, VIDIOCGPICT, &picture_format)) {
+ cerr << "Error: ioctl (VIDIOCGPICT)" << endl;
+ strncpy(errmsg, "ioctl (VIDIOCGPICT)", 1024);
+ return -1;
+ }
+ init(0);
+ }
+
+ // Check to see if it's really a philips webcam
+ if (ioctl(fd, VIDIOCPWCPROBE, &probe) == 0)
+ {
+ if (!strcmp(capability.name,probe.name))
+ {
+ IsPhilips = true;
+ type_=probe.type;
+ }
+ }
+
+ if (IsPhilips)
+ cerr << "Philips webcam type " << type_ << " detected" << endl;
+ else
+ {
+ strncpy(errmsg, "No Philips webcam detected.", 1024);
+ return -1;
+ }
+
+ cerr << "initial size w:" << window.width << " -- h: " << window.height << endl;
+
+
+ mmapInit();
+
+ setWhiteBalanceMode(PWC_WB_AUTO, errmsg);
+ multiplicateur_=1;
+ skippedFrame_=0;
+ lastGain_=getGain();
+
+ cerr << "All successful, returning\n";
+ return fd;
+}
+
+void V4L1_PWC::checkSize(int & x, int & y)
+{
+ if (x>=capability.maxwidth && y >= capability.maxheight)
+ {
+ x=capability.maxwidth;
+ y=capability.maxheight;
+ } else if (x>=352 && y >=288 && type_<700) {
+ x=352;y=288;
+ } else if (x>=320 && y >= 240) {
+ x=320;y=240;
+ } else if (x>=176 && y >=144 && type_<700 ) {
+ x=176;y=144;
+ } else if (x>=160 && y >=120 ) {
+ x=160;y=120;
+ } else {
+ x=capability.minwidth;
+ y=capability.minheight;
+ }
+}
+
+bool V4L1_PWC::setSize(int x, int y)
+{
+
+ int oldX, oldY;
+ char msg[ERRMSG_SIZ];
+ checkSize(x,y);
+
+ oldX = window.width;
+ oldY = window.height;
+
+ window.width=x;
+ window.height=y;
+
+ if (ioctl (fd, VIDIOCSWIN, &window))
+ {
+ snprintf(msg, ERRMSG_SIZ, "ioctl(VIDIOCSWIN) %s", strerror(errno));
+ cerr << msg << endl;
+ window.width=oldX;
+ window.height=oldY;
+ return false;
+ }
+ ioctl (fd, VIDIOCGWIN, &window);
+
+ cerr << "New size is x=" << window.width << " " << "y=" << window.height <<endl;
+
+ allocBuffers();
+
+ return true;
+}
+
+int V4L1_PWC::saveSettings(char *errmsg)
+{
+ if (ioctl(fd, VIDIOCPWCSUSER)==-1)
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSUSER %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+void V4L1_PWC::restoreSettings()
+ {
+ ioctl(fd, VIDIOCPWCRUSER);
+ getPictureSettings();
+}
+
+void V4L1_PWC::restoreFactorySettings()
+{
+ ioctl(fd, VIDIOCPWCFACTORY);
+ getPictureSettings();
+}
+
+int V4L1_PWC::setGain(int val, char *errmsg)
+ {
+ if(-1==ioctl(fd, VIDIOCPWCSAGC, &val))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSAGC %s", strerror(errno));
+ return -1;
+ }
+ else lastGain_=val;
+
+ cerr << "setGain "<<val<<endl;
+
+ return lastGain_;
+}
+
+int V4L1_PWC::getGain()
+{
+ int gain;
+ char msg[ERRMSG_SIZ];
+ static int cpt=0;
+ if ((cpt%4)==0)
+ {
+ if (-1==ioctl(fd, VIDIOCPWCGAGC, &gain))
+ {
+ //perror("VIDIOCPWCGAGC");
+ snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGAGC %s", strerror(errno));
+ cerr << msg << endl;
+ gain=lastGain_;
+ } else
+ {
+ ++cpt;
+ lastGain_=gain;
+ }
+ } else
+ {
+ ++cpt;
+ gain=lastGain_;
+ }
+ //cerr << "get gain "<<gain<<endl;
+ if (gain < 0) gain*=-1;
+ return gain;
+}
+
+int V4L1_PWC::setExposure(int val, char *errmsg)
+ {
+ //cout << "set exposure "<<val<<"\n";
+
+ if (-1==ioctl(fd, VIDIOCPWCSSHUTTER, &val))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSSHUTTER %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+void V4L1_PWC::setCompression(int val)
+{
+ ioctl(fd, VIDIOCPWCSCQUAL, &val);
+}
+
+int V4L1_PWC::getCompression()
+{
+ int gain;
+ ioctl(fd, VIDIOCPWCGCQUAL , &gain);
+ if (gain < 0) gain*=-1;
+ return gain;
+}
+
+int V4L1_PWC::setNoiseRemoval(int val, char *errmsg)
+{
+ if (-1 == ioctl(fd, VIDIOCPWCSDYNNOISE, &val))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCGDYNNOISE %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+int V4L1_PWC::getNoiseRemoval()
+{
+ int gain;
+ char msg[ERRMSG_SIZ];
+
+ if (-1 == ioctl(fd, VIDIOCPWCGDYNNOISE , &gain))
+ {
+ snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGDYNNOISE %s", strerror(errno));
+ cerr << msg << endl;
+ }
+
+ cout <<"get noise = "<<gain<<endl;
+ return gain;
+}
+
+int V4L1_PWC::setSharpness(int val, char *errmsg)
+ {
+ if (-1 == ioctl(fd, VIDIOCPWCSCONTOUR, &val))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSCONTOUR %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+int V4L1_PWC::getSharpness()
+{
+ int gain;
+ char msg[ERRMSG_SIZ];
+
+ if (-1 == ioctl(fd, VIDIOCPWCGCONTOUR, &gain))
+ {
+ snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGCONTOUR %s", strerror(errno));
+ cerr << msg << endl;
+ }
+
+ cout <<"get sharpness = "<<gain<<endl;
+ return gain;
+}
+
+int V4L1_PWC::setBackLight(bool val, char *errmsg)
+{
+ static int on=1;
+ static int off=0;
+ if (-1 == ioctl(fd,VIDIOCPWCSBACKLIGHT, & val?&on:&off))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSBACKLIGHT %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+bool V4L1_PWC::getBackLight()
+{
+ int val;
+ char msg[ERRMSG_SIZ];
+
+ if (-1 == ioctl(fd,VIDIOCPWCGBACKLIGHT, & val))
+ {
+ snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCSBACKLIGHT %s", strerror(errno));
+ cerr << msg << endl;
+ }
+
+ return val !=0;
+}
+
+int V4L1_PWC::setFlicker(bool val, char *errmsg)
+{
+ static int on=1;
+ static int off=0;
+ if (-1 == ioctl(fd,VIDIOCPWCSFLICKER, val?&on:&off))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "VIDIOCPWCSFLICKER %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+
+}
+
+bool V4L1_PWC::getFlicker()
+{
+ int val;
+ char msg[ERRMSG_SIZ];
+
+ if (-1 == ioctl(fd,VIDIOCPWCGFLICKER, & val))
+ {
+ snprintf(msg, ERRMSG_SIZ, "VIDIOCPWCGFLICKER %s", strerror(errno));
+ cerr << msg << endl;
+ }
+
+ return val !=0;
+}
+
+void V4L1_PWC::setGama(int val)
+{
+ picture_format.whiteness=val;
+ setPictureSettings();
+}
+
+int V4L1_PWC::getGama()
+{
+ return picture_format.whiteness;
+}
+
+int V4L1_PWC::setFrameRate(int value, char *errmsg)
+ {
+ window.flags = (window.flags & ~PWC_FPS_MASK) | ((value << PWC_FPS_SHIFT) & PWC_FPS_MASK);
+ if (ioctl(fd, VIDIOCSWIN, &window))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "setFrameRate %s", strerror(errno));
+ return -1;
+ }
+
+ ioctl(fd, VIDIOCGWIN, &window);
+ frameRate = value;
+
+ return 0;
+ //emit exposureTime(multiplicateur_/(double)getFrameRate());
+}
+
+int V4L1_PWC::getFrameRate()
+{
+ return ((window.flags&PWC_FPS_FRMASK)>>PWC_FPS_SHIFT);
+}
+
+int V4L1_PWC::getWhiteBalance()
+{
+ char msg[ERRMSG_SIZ];
+ struct pwc_whitebalance tmp_whitebalance;
+ tmp_whitebalance.mode = tmp_whitebalance.manual_red = tmp_whitebalance.manual_blue = tmp_whitebalance.read_red = tmp_whitebalance.read_blue = PWC_WB_AUTO;
+
+ if (ioctl(fd, VIDIOCPWCGAWB, &tmp_whitebalance))
+ {
+ snprintf(msg, ERRMSG_SIZ, "getWhiteBalance %s", strerror(errno));
+ cerr << msg << endl;
+ }
+ else
+ {
+#if 0
+ cout << "mode="<<tmp_whitebalance.mode
+ <<" mr="<<tmp_whitebalance.manual_red
+ <<" mb="<<tmp_whitebalance.manual_blue
+ <<" ar="<<tmp_whitebalance.read_red
+ <<" ab="<<tmp_whitebalance.read_blue
+ <<endl;
+#endif
+ /* manual_red and manual_blue are garbage :-( */
+ whiteBalanceMode_=tmp_whitebalance.mode;
+ }
+
+ return whiteBalanceMode_;
+
+ /*switch(whiteBalanceMode_) {
+ case PWC_WB_INDOOR:
+ setProperty("WhiteBalanceMode","Indor");
+ break;
+ case PWC_WB_OUTDOOR:
+ setProperty("WhiteBalanceMode","Outdoor");
+ break;
+ case PWC_WB_FL:
+ setProperty("WhiteBalanceMode","Neon");
+ break;
+ case PWC_WB_MANUAL:
+ setProperty("WhiteBalanceMode","Manual");
+ whiteBalanceRed_=tmp_whitebalance.manual_red;
+ whiteBalanceBlue_=tmp_whitebalance.manual_blue;
+
+ break;
+ case PWC_WB_AUTO:
+ setProperty("WhiteBalanceMode","Auto");
+ whiteBalanceRed_=tmp_whitebalance.read_red;
+ whiteBalanceBlue_=tmp_whitebalance.read_blue;
+ break;
+ default:
+ setProperty("WhiteBalanceMode","???");
+ }
+
+ emit whiteBalanceModeChange(whiteBalanceMode_);
+
+ if (((whiteBalanceMode_ == PWC_WB_AUTO) && liveWhiteBalance_)
+ || whiteBalanceMode_ != PWC_WB_AUTO) {
+ setProperty("WhiteBalanceRed",whiteBalanceRed_);
+ emit whiteBalanceRedChange(whiteBalanceRed_);
+ setProperty("WhiteBalanceBlue",whiteBalanceBlue_);
+ emit whiteBalanceBlueChange(whiteBalanceBlue_);
+ if (guiBuild()) {
+ remoteCTRLWBred_->show();
+ remoteCTRLWBblue_->show();
+ }
+ } else {
+ if (guiBuild()) {
+ remoteCTRLWBred_->hide();
+ remoteCTRLWBblue_->hide();
+ }
+ }
+ }*/
+}
+
+int V4L1_PWC::setWhiteBalance(char *errmsg)
+{
+ struct pwc_whitebalance wb;
+ wb.mode=whiteBalanceMode_;
+ if (wb.mode == PWC_WB_MANUAL)
+ {
+ wb.manual_red=whiteBalanceRed_;
+ wb.manual_blue=whiteBalanceBlue_;
+ }
+
+ if (ioctl(fd, VIDIOCPWCSAWB, &wb))
+ {
+ snprintf(errmsg, ERRMSG_SIZ, "setWhiteBalance %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+int V4L1_PWC::setWhiteBalanceMode(int val, char *errmsg)
+ {
+ if (val == whiteBalanceMode_)
+ return whiteBalanceMode_;
+
+ if (val != PWC_WB_AUTO)
+ {
+ if ( val != PWC_WB_MANUAL)
+ {
+ whiteBalanceMode_=val;
+ if (setWhiteBalance(errmsg) < 0)
+ return -1;
+ }
+
+ //whiteBalanceMode_=PWC_WB_AUTO;
+ whiteBalanceMode_= val;
+ if (setWhiteBalance(errmsg) < 0)
+ return -1;
+ getWhiteBalance();
+ }
+
+ /*if (guiBuild()) {
+ if (val != PWC_WB_AUTO
+ || ( liveWhiteBalance_ && (val ==PWC_WB_AUTO))) {
+ remoteCTRLWBred_->show();
+ remoteCTRLWBblue_->show();
+ } else {
+ remoteCTRLWBred_->hide();
+ remoteCTRLWBblue_->hide();
+ }
+ }*/
+
+ whiteBalanceMode_=val;
+ if (setWhiteBalance(errmsg) < 0)
+ return -1;
+ getWhiteBalance();
+
+ return 0;
+}
+
+int V4L1_PWC::setWhiteBalanceRed(int val, char *errmsg)
+{
+ whiteBalanceMode_ = PWC_WB_MANUAL;
+ whiteBalanceRed_=val;
+ if (setWhiteBalance(errmsg) < 0)
+ return -1;
+
+ return 0;
+}
+
+int V4L1_PWC::setWhiteBalanceBlue(int val, char *errmsg)
+{
+ whiteBalanceMode_ = PWC_WB_MANUAL;
+ whiteBalanceBlue_=val;
+ if (setWhiteBalance(errmsg) < 0)
+ return -1;
+
+ return 0;
+}
+
diff --git a/kstars/kstars/indi/webcam/v4l1_pwc.h b/kstars/kstars/indi/webcam/v4l1_pwc.h
new file mode 100644
index 00000000..ad0fab1f
--- /dev/null
+++ b/kstars/kstars/indi/webcam/v4l1_pwc.h
@@ -0,0 +1,89 @@
+/*
+ Phlips webcam driver for V4L 1
+ Copyright (C) 2005 by Jasem Mutlaq
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef V4L1_PWC_H
+#define V4L1_PWC_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "videodev.h"
+#include "v4l1_base.h"
+
+class V4L1_PWC : public V4L1_Base
+{
+ public:
+ V4L1_PWC();
+ ~V4L1_PWC();
+
+ int connectCam(const char * devpath, char *errmsg);
+
+ /* Philips related, from QAstrocam */
+ int saveSettings(char *errmsg);
+ void restoreSettings();
+ void restoreFactorySettings();
+ int setGain(int value, char *errmsg);
+ int getGain();
+ int setExposure(int val, char *errmsg);
+ void setCompression(int value);
+ int getCompression();
+ int setNoiseRemoval(int value, char *errmsg);
+ int getNoiseRemoval();
+ int setSharpness(int value, char *errmsg);
+ int getSharpness();
+ int setBackLight(bool val, char *errmsg);
+ bool getBackLight();
+ int setFlicker(bool val, char *errmsg);
+ bool getFlicker();
+ void setGama(int value);
+ int getGama();
+ int setFrameRate(int value, char *errmsg);
+ int getFrameRate();
+ int setWhiteBalance(char *errmsg);
+ int getWhiteBalance();
+ int setWhiteBalanceMode(int val, char *errmsg);
+ int setWhiteBalanceRed(int val, char *errmsg);
+ int setWhiteBalanceBlue(int val, char *errmsg);
+
+ /* TODO consider the SC modded cam after this
+ void setLongExposureTime(const QString& str);
+ void setFrameRateMultiplicateur(int value);*/
+
+
+ /* Updates */
+ //void updateFrame(int d, void *p);
+
+ /* Image Size */
+ void checkSize(int & x, int & y);
+ bool setSize(int x, int y);
+
+
+ private:
+ int whiteBalanceMode_;
+ int whiteBalanceRed_;
+ int whiteBalanceBlue_;
+ int lastGain_;
+ int multiplicateur_;
+ int skippedFrame_;
+ int type_;
+
+
+};
+
+#endif
diff --git a/kstars/kstars/indi/webcam/v4l2_base.cpp b/kstars/kstars/indi/webcam/v4l2_base.cpp
new file mode 100644
index 00000000..26ec3d51
--- /dev/null
+++ b/kstars/kstars/indi/webcam/v4l2_base.cpp
@@ -0,0 +1,1189 @@
+/*
+ Copyright (C) 2005 by Jasem Mutlaq
+
+ Based on V4L 2 Example
+ http://v4l2spec.bytesex.org/spec-single/v4l2.html#CAPTURE-EXAMPLE
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#include <iostream>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <asm/types.h> /* for videodev2.h */
+
+#include "ccvt.h"
+#include "v4l2_base.h"
+#include "../eventloop.h"
+#include "../indidevapi.h"
+
+#define ERRMSGSIZ 1024
+
+#define CLEAR(x) memset (&(x), 0, sizeof (x))
+
+using namespace std;
+
+V4L2_Base::V4L2_Base()
+{
+ frameRate=10;
+ selectCallBackID = -1;
+ dropFrame = false;
+
+ xmax = xmin = 160;
+ ymax = ymin = 120;
+
+ io = IO_METHOD_MMAP;
+ fd = -1;
+ buffers = NULL;
+ n_buffers = 0;
+
+ YBuf = NULL;
+ UBuf = NULL;
+ VBuf = NULL;
+ colorBuffer = NULL;
+ rgb24_buffer = NULL;
+ callback = NULL;
+
+}
+
+V4L2_Base::~V4L2_Base()
+{
+
+ delete (YBuf);
+ delete (UBuf);
+ delete (VBuf);
+ delete (colorBuffer);
+ delete (rgb24_buffer);
+
+}
+
+int V4L2_Base::xioctl(int fd, int request, void *arg)
+{
+ int r;
+
+ do r = ioctl (fd, request, arg);
+ while (-1 == r && EINTR == errno);
+
+ return r;
+}
+
+int V4L2_Base::errno_exit(const char *s, char *errmsg)
+{
+ fprintf (stderr, "%s error %d, %s\n",
+ s, errno, strerror (errno));
+
+ snprintf(errmsg, ERRMSGSIZ, "%s error %d, %s\n", s, errno, strerror (errno));
+
+ return -1;
+}
+
+int V4L2_Base::connectCam(const char * devpath, char *errmsg , int pixelFormat , int width , int height )
+{
+ frameRate=10;
+ selectCallBackID = -1;
+ dropFrame = false;
+
+ if (open_device (devpath, errmsg) < 0)
+ return -1;
+
+ if (init_device(errmsg, pixelFormat, width, height) < 0)
+ return -1;
+
+ cerr << "V4L 2 - All successful, returning\n";
+ return fd;
+}
+
+void V4L2_Base::disconnectCam()
+{
+ char errmsg[ERRMSGSIZ];
+ delete YBuf;
+ delete UBuf;
+ delete VBuf;
+ YBuf = UBuf = VBuf = NULL;
+
+ if (selectCallBackID != -1)
+ rmCallback(selectCallBackID);
+
+ stop_capturing (errmsg);
+
+ uninit_device (errmsg);
+
+ close_device ();
+
+ fprintf(stderr, "Disconnect cam\n");
+}
+
+int V4L2_Base::read_frame(char *errmsg)
+{
+ struct v4l2_buffer buf;
+ unsigned int i;
+ //cerr << "in read Frame" << endl;
+
+ switch (io) {
+ case IO_METHOD_READ:
+ if (-1 == read (fd, buffers[0].start, buffers[0].length)) {
+ switch (errno) {
+ case EAGAIN:
+ return 0;
+
+ case EIO:
+ /* Could ignore EIO, see spec. */
+
+ /* fall through */
+
+ default:
+ return errno_exit ("read", errmsg);
+ }
+ }
+
+ //process_image (buffers[0].start);
+
+ break;
+
+ case IO_METHOD_MMAP:
+ CLEAR (buf);
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+
+ if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
+ switch (errno) {
+ case EAGAIN:
+ return 0;
+
+ case EIO:
+ /* Could ignore EIO, see spec. */
+
+ /* fall through */
+
+ default:
+ return errno_exit ("VIDIOC_DQBUF", errmsg);
+ }
+ }
+
+ assert (buf.index < n_buffers);
+
+ switch (fmt.fmt.pix.pixelformat)
+ {
+ case V4L2_PIX_FMT_YUV420:
+ memcpy(YBuf,((unsigned char *) buffers[buf.index].start), fmt.fmt.pix.width * fmt.fmt.pix.height);
+ memcpy(UBuf,((unsigned char *) buffers[buf.index].start) + fmt.fmt.pix.width * fmt.fmt.pix.height, (fmt.fmt.pix.width/2) * (fmt.fmt.pix.height/2));
+ memcpy(VBuf,((unsigned char *) buffers[buf.index].start) + fmt.fmt.pix.width * fmt.fmt.pix.height + (fmt.fmt.pix.width/2) * (fmt.fmt.pix.height/2), (fmt.fmt.pix.width/2) * (fmt.fmt.pix.width/2));
+ break;
+
+ case V4L2_PIX_FMT_YUYV:
+ ccvt_yuyv_420p( fmt.fmt.pix.width , fmt.fmt.pix.height, buffers[buf.index].start, YBuf, UBuf, VBuf);
+ break;
+
+ case V4L2_PIX_FMT_RGB24:
+ RGB2YUV(fmt.fmt.pix.width, fmt.fmt.pix.height, buffers[buf.index].start, YBuf, UBuf, VBuf, 0);
+ break;
+
+ case V4L2_PIX_FMT_SBGGR8:
+ bayer2rgb24(rgb24_buffer, ((unsigned char *) buffers[buf.index].start), fmt.fmt.pix.width, fmt.fmt.pix.height);
+ break;
+ }
+
+ if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
+ return errno_exit ("VIDIOC_QBUF", errmsg);
+
+ if (dropFrame)
+ {
+ dropFrame = false;
+ return 0;
+ }
+
+ /* Call provided callback function if any */
+ if (callback)
+ (*callback)(uptr);
+
+ break;
+
+ case IO_METHOD_USERPTR:
+ CLEAR (buf);
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_USERPTR;
+
+ if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
+ switch (errno) {
+ case EAGAIN:
+ return 0;
+
+ case EIO:
+ /* Could ignore EIO, see spec. */
+
+ /* fall through */
+
+ default:
+ errno_exit ("VIDIOC_DQBUF", errmsg);
+ }
+ }
+
+ for (i = 0; i < n_buffers; ++i)
+ if (buf.m.userptr == (unsigned long) buffers[i].start
+ && buf.length == buffers[i].length)
+ break;
+
+ assert (i < n_buffers);
+
+ //process_image ((void *) buf.m.userptr);
+
+ if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
+ errno_exit ("VIDIOC_QBUF", errmsg);
+
+ break;
+ }
+
+ return 0;
+}
+
+int V4L2_Base::stop_capturing(char *errmsg)
+{
+ enum v4l2_buf_type type;
+
+ switch (io) {
+ case IO_METHOD_READ:
+ /* Nothing to do. */
+ break;
+
+ case IO_METHOD_MMAP:
+ case IO_METHOD_USERPTR:
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ IERmCallback(selectCallBackID);
+ selectCallBackID = -1;
+
+ dropFrame = true;
+
+ if (-1 == xioctl (fd, VIDIOC_STREAMOFF, &type))
+ return errno_exit ("VIDIOC_STREAMOFF", errmsg);
+
+
+
+ break;
+ }
+
+ return 0;
+}
+
+int V4L2_Base::start_capturing(char * errmsg)
+{
+ unsigned int i;
+ enum v4l2_buf_type type;
+
+ switch (io) {
+ case IO_METHOD_READ:
+ /* Nothing to do. */
+ break;
+
+ case IO_METHOD_MMAP:
+ for (i = 0; i < n_buffers; ++i) {
+ struct v4l2_buffer buf;
+
+ CLEAR (buf);
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = i;
+
+ if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
+ return errno_exit ("VIDIOC_QBUF", errmsg);
+
+ }
+
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
+ return errno_exit ("VIDIOC_STREAMON", errmsg);
+
+
+
+ selectCallBackID = IEAddCallback(fd, newFrame, this);
+
+ break;
+
+ case IO_METHOD_USERPTR:
+ for (i = 0; i < n_buffers; ++i) {
+ struct v4l2_buffer buf;
+
+ CLEAR (buf);
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_USERPTR;
+ buf.m.userptr = (unsigned long) buffers[i].start;
+ buf.length = buffers[i].length;
+
+ if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
+ return errno_exit ("VIDIOC_QBUF", errmsg);
+ }
+
+
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
+ return errno_exit ("VIDIOC_STREAMON", errmsg);
+
+ break;
+ }
+
+ return 0;
+
+}
+
+void V4L2_Base::newFrame(int /*fd*/, void *p)
+{
+ char errmsg[ERRMSGSIZ];
+
+ ( (V4L2_Base *) (p))->read_frame(errmsg);
+
+}
+
+int V4L2_Base::uninit_device(char *errmsg)
+{
+
+ switch (io) {
+ case IO_METHOD_READ:
+ free (buffers[0].start);
+ break;
+
+ case IO_METHOD_MMAP:
+ for (unsigned int i = 0; i < n_buffers; ++i)
+ if (-1 == munmap (buffers[i].start, buffers[i].length))
+ return errno_exit ("munmap", errmsg);
+ break;
+
+ case IO_METHOD_USERPTR:
+ for (unsigned int i = 0; i < n_buffers; ++i)
+ free (buffers[i].start);
+ break;
+ }
+
+ free (buffers);
+
+ return 0;
+}
+
+void V4L2_Base::init_read(unsigned int buffer_size)
+{
+ buffers = (buffer *) calloc (1, sizeof (*buffers));
+
+ if (!buffers) {
+ fprintf (stderr, "Out of memory\n");
+ exit (EXIT_FAILURE);
+ }
+
+ buffers[0].length = buffer_size;
+ buffers[0].start = malloc (buffer_size);
+
+ if (!buffers[0].start) {
+ fprintf (stderr, "Out of memory\n");
+ exit (EXIT_FAILURE);
+ }
+}
+
+int V4L2_Base::init_mmap(char *errmsg)
+{
+ struct v4l2_requestbuffers req;
+
+ CLEAR (req);
+
+ req.count = 4;
+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ req.memory = V4L2_MEMORY_MMAP;
+
+ if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) {
+ if (EINVAL == errno) {
+ fprintf (stderr, "%s does not support "
+ "memory mapping\n", dev_name);
+ snprintf(errmsg, ERRMSGSIZ, "%s does not support "
+ "memory mapping\n", dev_name);
+ return -1;
+ } else {
+ return errno_exit ("VIDIOC_REQBUFS", errmsg);
+ }
+ }
+
+ if (req.count < 2) {
+ fprintf (stderr, "Insufficient buffer memory on %s\n",
+ dev_name);
+ snprintf(errmsg, ERRMSGSIZ, "Insufficient buffer memory on %s\n",
+ dev_name);
+ return -1;
+ }
+
+ buffers = (buffer *) calloc (req.count, sizeof (*buffers));
+
+ if (!buffers)
+ {
+ fprintf (stderr, "buffers. Out of memory\n");
+ strncpy(errmsg, "buffers. Out of memory\n", ERRMSGSIZ);
+ return -1;
+ }
+
+ for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
+ {
+ struct v4l2_buffer buf;
+
+ CLEAR (buf);
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = n_buffers;
+
+ if (-1 == xioctl (fd, VIDIOC_QUERYBUF, &buf))
+ return errno_exit ("VIDIOC_QUERYBUF", errmsg);
+
+ buffers[n_buffers].length = buf.length;
+ buffers[n_buffers].start =
+ mmap (NULL /* start anywhere */,
+ buf.length,
+ PROT_READ | PROT_WRITE /* required */,
+ MAP_SHARED /* recommended */,
+ fd, buf.m.offset);
+
+ if (MAP_FAILED == buffers[n_buffers].start)
+ return errno_exit ("mmap", errmsg);
+ }
+
+ return 0;
+}
+
+void V4L2_Base::init_userp(unsigned int buffer_size)
+{
+ struct v4l2_requestbuffers req;
+ char errmsg[ERRMSGSIZ];
+
+ CLEAR (req);
+
+ req.count = 4;
+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ req.memory = V4L2_MEMORY_USERPTR;
+
+ if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) {
+ if (EINVAL == errno) {
+ fprintf (stderr, "%s does not support "
+ "user pointer i/o\n", dev_name);
+ exit (EXIT_FAILURE);
+ } else {
+ errno_exit ("VIDIOC_REQBUFS", errmsg);
+ }
+ }
+
+ buffers = (buffer *) calloc (4, sizeof (*buffers));
+
+ if (!buffers) {
+ fprintf (stderr, "Out of memory\n");
+ exit (EXIT_FAILURE);
+ }
+
+ for (n_buffers = 0; n_buffers < 4; ++n_buffers) {
+ buffers[n_buffers].length = buffer_size;
+ buffers[n_buffers].start = malloc (buffer_size);
+
+ if (!buffers[n_buffers].start) {
+ fprintf (stderr, "Out of memory\n");
+ exit (EXIT_FAILURE);
+ }
+ }
+}
+
+int V4L2_Base::init_device(char *errmsg, int pixelFormat , int width, int height)
+{
+ unsigned int min;
+
+ if (-1 == xioctl (fd, VIDIOC_QUERYCAP, &cap))
+ {
+ if (EINVAL == errno) {
+ fprintf (stderr, "%s is no V4L2 device\n",
+ dev_name);
+ snprintf(errmsg, ERRMSGSIZ, "%s is no V4L2 device\n", dev_name);
+ return -1;
+ } else {
+ return errno_exit ("VIDIOC_QUERYCAP", errmsg);
+ }
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
+ {
+ fprintf (stderr, "%s is no video capture device\n",
+ dev_name);
+ snprintf(errmsg, ERRMSGSIZ, "%s is no video capture device\n", dev_name);
+ return -1;
+ }
+
+ switch (io)
+ {
+ case IO_METHOD_READ:
+ if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
+ fprintf (stderr, "%s does not support read i/o\n",
+ dev_name);
+ snprintf(errmsg, ERRMSGSIZ, "%s does not support read i/o\n",
+ dev_name);
+ return -1;
+ }
+
+ break;
+
+ case IO_METHOD_MMAP:
+ case IO_METHOD_USERPTR:
+ if (!(cap.capabilities & V4L2_CAP_STREAMING))
+ {
+ fprintf (stderr, "%s does not support streaming i/o\n",
+ dev_name);
+ snprintf(errmsg, ERRMSGSIZ, "%s does not support streaming i/o\n",
+ dev_name);
+ return -1;
+ }
+
+ break;
+ }
+
+ /* Select video input, video standard and tune here. */
+
+ cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (-1 == xioctl (fd, VIDIOC_CROPCAP, &cropcap)) {
+ /* Errors ignored. */
+ }
+
+ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ crop.c = cropcap.defrect; /* reset to default */
+
+ if (-1 == xioctl (fd, VIDIOC_S_CROP, &crop)) {
+ switch (errno) {
+ case EINVAL:
+ /* Cropping not supported. */
+ break;
+ default:
+ /* Errors ignored. */
+ break;
+ }
+ }
+
+ CLEAR (fmt);
+
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.width = width;
+ fmt.fmt.pix.height = height;
+ fmt.fmt.pix.pixelformat = pixelFormat;
+ //fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+ if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt))
+ return errno_exit ("VIDIOC_S_FMT", errmsg);
+
+ /* Note VIDIOC_S_FMT may change width and height. */
+
+ /* Buggy driver paranoia. */
+ min = fmt.fmt.pix.width * 2;
+ if (fmt.fmt.pix.bytesperline < min)
+ fmt.fmt.pix.bytesperline = min;
+ min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
+ if (fmt.fmt.pix.sizeimage < min)
+ fmt.fmt.pix.sizeimage = min;
+
+ /* Let's get the actual size */
+ CLEAR(fmt);
+
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (-1 == xioctl (fd, VIDIOC_G_FMT, &fmt))
+ return errno_exit ("VIDIOC_G_FMT", errmsg);
+
+ cerr << "width: " << fmt.fmt.pix.width << " - height: " << fmt.fmt.pix.height << endl;
+
+ switch (pixelFormat)
+ {
+ case V4L2_PIX_FMT_YUV420:
+ cerr << "pixel format: V4L2_PIX_FMT_YUV420" << endl;
+ break;
+
+ case V4L2_PIX_FMT_YUYV:
+ cerr << "pixel format: V4L2_PIX_FMT_YUYV" << endl;
+ break;
+
+ case V4L2_PIX_FMT_RGB24:
+ cerr << "pixel format: V4L2_PIX_FMT_RGB24" << endl;
+ break;
+
+ case V4L2_PIX_FMT_SBGGR8:
+ cerr << "pixel format: V4L2_PIX_FMT_SBGGR8" << endl;
+ break;
+
+ }
+
+ findMinMax();
+
+ allocBuffers();
+
+ switch (io)
+ {
+ case IO_METHOD_READ:
+ init_read (fmt.fmt.pix.sizeimage);
+ break;
+
+ case IO_METHOD_MMAP:
+ return init_mmap(errmsg);
+ break;
+
+ case IO_METHOD_USERPTR:
+ init_userp (fmt.fmt.pix.sizeimage);
+ break;
+ }
+
+ return 0;
+}
+
+void V4L2_Base::close_device(void)
+{
+ char errmsg[ERRMSGSIZ];
+
+ if (-1 == close (fd))
+ errno_exit ("close", errmsg);
+
+ fd = -1;
+}
+
+int V4L2_Base::open_device(const char *devpath, char *errmsg)
+{
+ struct stat st;
+
+ strncpy(dev_name, devpath, 64);
+
+ if (-1 == stat (dev_name, &st)) {
+ fprintf (stderr, "Cannot identify '%s': %d, %s\n",
+ dev_name, errno, strerror (errno));
+ snprintf(errmsg, ERRMSGSIZ, "Cannot identify '%s': %d, %s\n",
+ dev_name, errno, strerror (errno));
+ return -1;
+ }
+
+ if (!S_ISCHR (st.st_mode))
+ {
+ fprintf (stderr, "%s is no device\n", dev_name);
+ snprintf(errmsg, ERRMSGSIZ, "%s is no device\n", dev_name);
+ return -1;
+ }
+
+ fd = open (dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
+
+ if (-1 == fd)
+ {
+ fprintf (stderr, "Cannot open '%s': %d, %s\n",
+ dev_name, errno, strerror (errno));
+ snprintf(errmsg, ERRMSGSIZ, "Cannot open '%s': %d, %s\n",
+ dev_name, errno, strerror (errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+int V4L2_Base::getWidth()
+{
+ return fmt.fmt.pix.width;
+}
+
+int V4L2_Base::getHeight()
+{
+ return fmt.fmt.pix.height;
+}
+
+void V4L2_Base::setFPS(int fps)
+{
+ frameRate = 15;//fps;
+}
+
+int V4L2_Base::getFPS()
+{
+ return 15;
+}
+
+char * V4L2_Base::getDeviceName()
+{
+ return ((char *) cap.card);
+}
+
+void V4L2_Base::allocBuffers()
+{
+ delete (YBuf); YBuf = NULL;
+ delete (UBuf); UBuf = NULL;
+ delete (VBuf); VBuf = NULL;
+ delete (colorBuffer); colorBuffer = NULL;
+ delete (rgb24_buffer); rgb24_buffer = NULL;
+
+ YBuf= new unsigned char[ fmt.fmt.pix.width * fmt.fmt.pix.height];
+ UBuf= new unsigned char[ fmt.fmt.pix.width * fmt.fmt.pix.height];
+ VBuf= new unsigned char[ fmt.fmt.pix.width * fmt.fmt.pix.height];
+ colorBuffer = new unsigned char[fmt.fmt.pix.width * fmt.fmt.pix.height * 4];
+
+ if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_SBGGR8)
+ rgb24_buffer = new unsigned char[fmt.fmt.pix.width * fmt.fmt.pix.height * 3];
+}
+
+void V4L2_Base::getMaxMinSize(int & x_max, int & y_max, int & x_min, int & y_min)
+{
+ x_max = xmax; y_max = ymax; x_min = xmin; y_min = ymin;
+}
+
+int V4L2_Base::setSize(int x, int y)
+{
+ char errmsg[ERRMSGSIZ];
+ int oldW, oldH;
+
+ oldW = fmt.fmt.pix.width;
+ oldH = fmt.fmt.pix.height;
+
+ fmt.fmt.pix.width = x;
+ fmt.fmt.pix.height = y;
+
+ if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt))
+ {
+ fmt.fmt.pix.width = oldW;
+ fmt.fmt.pix.height = oldH;
+ return errno_exit ("VIDIOC_S_FMT", errmsg);
+ }
+
+ /* PWC bug? It seems that setting the "wrong" width and height will mess something in the driver.
+ Only 160x120, 320x280, and 640x480 are accepted. If I try to set it for example to 300x200, it wii
+ get set to 320x280, which is fine, but then the video information is messed up for some reason. */
+ xioctl (fd, VIDIOC_S_FMT, &fmt);
+
+
+ allocBuffers();
+
+ return 0;
+}
+
+void V4L2_Base::setContrast(int val)
+{
+ /*picture_.contrast=val;
+ updatePictureSettings();*/
+}
+
+int V4L2_Base::getContrast()
+{
+ return 255;//picture_.contrast;
+}
+
+void V4L2_Base::setBrightness(int val)
+{
+ /*picture_.brightness=val;
+ updatePictureSettings();*/
+}
+
+int V4L2_Base::getBrightness()
+{
+ return 255;//picture_.brightness;
+}
+
+void V4L2_Base::setColor(int val)
+{
+ /*picture_.colour=val;
+ updatePictureSettings();*/
+}
+
+int V4L2_Base::getColor()
+{
+ return 255; //picture_.colour;
+}
+
+void V4L2_Base::setHue(int val)
+{
+ /*picture_.hue=val;
+ updatePictureSettings();*/
+}
+
+int V4L2_Base::getHue()
+{
+ return 255;//picture_.hue;
+}
+
+void V4L2_Base::setWhiteness(int val)
+{
+ /*picture_.whiteness=val;
+ updatePictureSettings();*/
+}
+
+int V4L2_Base::getWhiteness()
+{
+ return 255;//picture_.whiteness;
+}
+
+void V4L2_Base::setPictureSettings()
+{
+ /*if (ioctl(device_, VIDIOCSPICT, &picture_) ) {
+ cerr << "updatePictureSettings" << endl;
+ }
+ ioctl(device_, VIDIOCGPICT, &picture_);*/
+}
+
+void V4L2_Base::getPictureSettings()
+{
+ /*if (ioctl(device_, VIDIOCGPICT, &picture_) )
+ {
+ cerr << "refreshPictureSettings" << endl;
+ }*/
+}
+
+unsigned char * V4L2_Base::getY()
+{
+ if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_SBGGR8)
+ RGB2YUV(fmt.fmt.pix.width, fmt.fmt.pix.height, rgb24_buffer, YBuf, UBuf, VBuf, 0);
+
+ return YBuf;
+}
+
+unsigned char * V4L2_Base::getU()
+{
+ return UBuf;
+}
+
+unsigned char * V4L2_Base::getV()
+{
+ return VBuf;
+}
+
+unsigned char * V4L2_Base::getColorBuffer()
+{
+ //cerr << "in get color buffer " << endl;
+
+ switch (fmt.fmt.pix.pixelformat)
+ {
+ case V4L2_PIX_FMT_YUV420:
+ ccvt_420p_bgr32(fmt.fmt.pix.width, fmt.fmt.pix.height,
+ buffers[0].start, (void*)colorBuffer);
+ break;
+
+ case V4L2_PIX_FMT_YUYV:
+ ccvt_yuyv_bgr32(fmt.fmt.pix.width, fmt.fmt.pix.height,
+ buffers[0].start, (void*)colorBuffer);
+ break;
+
+ case V4L2_PIX_FMT_RGB24:
+ ccvt_rgb24_bgr32(fmt.fmt.pix.width, fmt.fmt.pix.height,
+ buffers[0].start, (void*)colorBuffer);
+ break;
+
+ case V4L2_PIX_FMT_SBGGR8:
+ ccvt_rgb24_bgr32(fmt.fmt.pix.width, fmt.fmt.pix.height,
+ rgb24_buffer, (void*)colorBuffer);
+ break;
+
+ default:
+ break;
+ }
+
+ return colorBuffer;
+}
+
+void V4L2_Base::registerCallback(WPF *fp, void *ud)
+{
+ callback = fp;
+ uptr = ud;
+}
+
+void V4L2_Base::findMinMax()
+{
+ char errmsg[ERRMSGSIZ];
+ struct v4l2_format tryfmt;
+ CLEAR(tryfmt);
+
+ xmin = xmax = fmt.fmt.pix.width;
+ ymin = ymax = fmt.fmt.pix.height;
+
+ tryfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ tryfmt.fmt.pix.width = 10;
+ tryfmt.fmt.pix.height = 10;
+ tryfmt.fmt.pix.pixelformat = fmt.fmt.pix.pixelformat;
+ tryfmt.fmt.pix.field = fmt.fmt.pix.field;
+
+ if (-1 == xioctl (fd, VIDIOC_TRY_FMT, &tryfmt))
+ {
+ errno_exit ("VIDIOC_TRY_FMT 1", errmsg);
+ return;
+ }
+
+ xmin = tryfmt.fmt.pix.width;
+ ymin = tryfmt.fmt.pix.height;
+
+ tryfmt.fmt.pix.width = 1600;
+ tryfmt.fmt.pix.height = 1200;
+
+ if (-1 == xioctl (fd, VIDIOC_TRY_FMT, &tryfmt))
+ {
+ errno_exit ("VIDIOC_TRY_FMT 2", errmsg);
+ return;
+ }
+
+ xmax = tryfmt.fmt.pix.width;
+ ymax = tryfmt.fmt.pix.height;
+
+ cerr << "Min X: " << xmin << " - Max X: " << xmax << " - Min Y: " << ymin << " - Max Y: " << ymax << endl;
+}
+
+void V4L2_Base::enumerate_ctrl (void)
+{
+ char errmsg[ERRMSGSIZ];
+ CLEAR(queryctrl);
+
+ for (queryctrl.id = V4L2_CID_BASE; queryctrl.id < V4L2_CID_LASTP1; queryctrl.id++)
+ {
+ if (0 == xioctl (fd, VIDIOC_QUERYCTRL, &queryctrl))
+ {
+ cerr << "Control " << queryctrl.name << endl;
+
+ if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ continue;
+
+ cerr << "Control " << queryctrl.name << endl;
+
+ if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
+ enumerate_menu ();
+ } else
+ {
+ if (errno == EINVAL)
+ continue;
+
+ errno_exit("VIDIOC_QUERYCTRL", errmsg);
+ return;
+ }
+ }
+
+ for (queryctrl.id = V4L2_CID_PRIVATE_BASE; ; queryctrl.id++)
+ {
+ if (0 == xioctl (fd, VIDIOC_QUERYCTRL, &queryctrl))
+ {
+ cerr << "Private Control " << queryctrl.name << endl;
+
+ if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ continue;
+
+ if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
+ enumerate_menu ();
+ } else {
+ if (errno == EINVAL)
+ break;
+
+ errno_exit ("VIDIOC_QUERYCTRL", errmsg);
+ return;
+ }
+
+ }
+
+}
+
+void V4L2_Base::enumerate_menu (void)
+{
+ char errmsg[ERRMSGSIZ];
+ cerr << " Menu items:" << endl;
+
+ CLEAR(querymenu);
+ querymenu.id = queryctrl.id;
+
+ for (querymenu.index = queryctrl.minimum; querymenu.index <= queryctrl.maximum; querymenu.index++)
+ {
+ if (0 == xioctl (fd, VIDIOC_QUERYMENU, &querymenu))
+ {
+ cerr << " " << querymenu.name << endl;
+ } else
+ {
+ errno_exit("VIDIOC_QUERYMENU", errmsg);
+ return;
+ }
+ }
+}
+
+int V4L2_Base::query_ctrl(unsigned int ctrl_id, double & ctrl_min, double & ctrl_max, double & ctrl_step, double & ctrl_value, char *errmsg)
+{
+
+ struct v4l2_control control;
+
+ CLEAR(queryctrl);
+
+ queryctrl.id = ctrl_id;
+
+ if (-1 == ioctl (fd, VIDIOC_QUERYCTRL, &queryctrl))
+ {
+ if (errno != EINVAL)
+ return errno_exit ("VIDIOC_QUERYCTRL", errmsg);
+
+ else
+ {
+ cerr << "#" << ctrl_id << " is not supported" << endl;
+ snprintf(errmsg, ERRMSGSIZ, "# %d is not supported", ctrl_id);
+ return -1;
+ }
+ } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ {
+ cerr << "#" << ctrl_id << " is disabled" << endl;
+ snprintf(errmsg, ERRMSGSIZ, "# %d is disabled", ctrl_id);
+ return -1;
+ }
+
+ ctrl_min = queryctrl.minimum;
+ ctrl_max = queryctrl.maximum;
+ ctrl_step = queryctrl.step;
+ ctrl_value = queryctrl.default_value;
+
+ /* Get current value */
+ CLEAR(control);
+ control.id = ctrl_id;
+
+ if (0 == xioctl(fd, VIDIOC_G_CTRL, &control))
+ ctrl_value = control.value;
+
+ cerr << queryctrl.name << " -- min: " << ctrl_min << " max: " << ctrl_max << " step: " << ctrl_step << " value: " << ctrl_value << endl;
+
+ return 0;
+
+}
+
+int V4L2_Base::queryINTControls(INumberVectorProperty *nvp)
+{
+ struct v4l2_control control;
+ char errmsg[ERRMSGSIZ];
+ CLEAR(queryctrl);
+ INumber *numbers = NULL;
+ unsigned int *num_ctrls = NULL;
+ int nnum=0;
+
+ for (queryctrl.id = V4L2_CID_BASE; queryctrl.id < V4L2_CID_LASTP1; queryctrl.id++)
+ {
+ if (0 == ioctl (fd, VIDIOC_QUERYCTRL, &queryctrl))
+ {
+ if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ {
+ cerr << queryctrl.name << " is disabled." << endl;
+ continue;
+ }
+
+ if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
+ {
+ numbers = (numbers == NULL) ? (INumber *) malloc (sizeof(INumber)) :
+ (INumber *) realloc (numbers, (nnum+1) * sizeof (INumber));
+
+ num_ctrls = (num_ctrls == NULL) ? (unsigned int *) malloc (sizeof (unsigned int)) :
+ (unsigned int *) realloc (num_ctrls, (nnum+1) * sizeof (unsigned int));
+
+ strncpy(numbers[nnum].name, ((char *) queryctrl.name) , MAXINDINAME);
+ strncpy(numbers[nnum].label, ((char *) queryctrl.name), MAXINDILABEL);
+ strncpy(numbers[nnum].format, "%0.f", MAXINDIFORMAT);
+ numbers[nnum].min = queryctrl.minimum;
+ numbers[nnum].max = queryctrl.maximum;
+ numbers[nnum].step = queryctrl.step;
+ numbers[nnum].value = queryctrl.default_value;
+
+ /* Get current value if possible */
+ CLEAR(control);
+ control.id = queryctrl.id;
+ if (0 == xioctl(fd, VIDIOC_G_CTRL, &control))
+ numbers[nnum].value = control.value;
+
+ /* Store ID info in INumber. This is the first time ever I make use of aux0!! */
+ num_ctrls[nnum] = queryctrl.id;
+
+ cerr << queryctrl.name << " -- min: " << queryctrl.minimum << " max: " << queryctrl.maximum << " step: " << queryctrl.step << " value: " << numbers[nnum].value << endl;
+
+ nnum++;
+
+ }
+ } else if (errno != EINVAL)
+ return errno_exit ("VIDIOC_QUERYCTRL", errmsg);
+
+ }
+
+ for (queryctrl.id = V4L2_CID_PRIVATE_BASE; ; queryctrl.id++)
+ {
+ if (0 == ioctl (fd, VIDIOC_QUERYCTRL, &queryctrl))
+ {
+ if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ {
+ cerr << queryctrl.name << " is disabled." << endl;
+ continue;
+ }
+
+ if (queryctrl.type == V4L2_CTRL_TYPE_INTEGER)
+ {
+ numbers = (numbers == NULL) ? (INumber *) malloc (sizeof(INumber)) :
+ (INumber *) realloc (numbers, (nnum+1) * sizeof (INumber));
+
+ num_ctrls = (num_ctrls == NULL) ? (unsigned int *) malloc (sizeof (unsigned int)) :
+ (unsigned int *) realloc (num_ctrls, (nnum+1) * sizeof (unsigned int));
+
+ strncpy(numbers[nnum].name, ((char *) queryctrl.name) , MAXINDINAME);
+ strncpy(numbers[nnum].label, ((char *) queryctrl.name), MAXINDILABEL);
+ strncpy(numbers[nnum].format, "%0.f", MAXINDIFORMAT);
+ numbers[nnum].min = queryctrl.minimum;
+ numbers[nnum].max = queryctrl.maximum;
+ numbers[nnum].step = queryctrl.step;
+ numbers[nnum].value = queryctrl.default_value;
+
+ /* Get current value if possible */
+ CLEAR(control);
+ control.id = queryctrl.id;
+ if (0 == xioctl(fd, VIDIOC_G_CTRL, &control))
+ numbers[nnum].value = control.value;
+
+ /* Store ID info in INumber. This is the first time ever I make use of aux0!! */
+ num_ctrls[nnum] = queryctrl.id;
+
+ nnum++;
+
+ }
+ }
+ else break;
+ }
+
+ /* Store numbers in aux0 */
+ for (int i=0; i < nnum; i++)
+ numbers[i].aux0 = &num_ctrls[i];
+
+ nvp->np = numbers;
+ nvp->nnp = nnum;
+
+ return nnum;
+
+}
+
+int V4L2_Base::setINTControl(unsigned int ctrl_id, double new_value, char *errmsg)
+{
+ struct v4l2_control control;
+
+ CLEAR(control);
+
+ cerr << "The id is " << ctrl_id << " new value is " << new_value << endl;
+
+ control.id = ctrl_id;
+ control.value = (int) new_value;
+
+ if (-1 == xioctl(fd, VIDIOC_S_CTRL, &control))
+ return errno_exit ("VIDIOC_S_CTRL", errmsg);
+
+ return 0;
+}
+
diff --git a/kstars/kstars/indi/webcam/v4l2_base.h b/kstars/kstars/indi/webcam/v4l2_base.h
new file mode 100644
index 00000000..668c77c9
--- /dev/null
+++ b/kstars/kstars/indi/webcam/v4l2_base.h
@@ -0,0 +1,141 @@
+/*
+ Copyright (C) 2005 by Jasem Mutlaq
+
+ Based on V4L 2 Example
+ http://v4l2spec.bytesex.org/spec-single/v4l2.html#CAPTURE-EXAMPLE
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+#ifndef V4L2_BASE_H
+#define V4L2_BASE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "videodev2.h"
+#include "../eventloop.h"
+#include "../indidevapi.h"
+
+#define VIDEO_COMPRESSION_LEVEL 4
+
+class V4L2_Base
+{
+ public:
+ V4L2_Base();
+ virtual ~V4L2_Base();
+
+ typedef enum { IO_METHOD_READ, IO_METHOD_MMAP, IO_METHOD_USERPTR } io_method;
+
+ struct buffer
+ {
+ void * start;
+ size_t length;
+ };
+
+ /* Connection */
+ virtual int connectCam(const char * devpath, char *errmsg, int pixelFormat = V4L2_PIX_FMT_YUYV , int width = 160, int height = 120);
+ virtual void disconnectCam();
+ char * getDeviceName();
+
+ /* Image settings */
+ int getBrightness();
+ int getContrast();
+ int getColor();
+ int getHue();
+ int getWhiteness();
+ void setContrast(int val);
+ void setBrightness(int val);
+ void setColor(int val);
+ void setHue(int val);
+ void setWhiteness(int val);
+
+ /* Updates */
+ void callFrame(void *p);
+ void setPictureSettings();
+ void getPictureSettings();
+
+ /* Image Size */
+ int getWidth();
+ int getHeight();
+ virtual int setSize(int x, int y);
+ virtual void getMaxMinSize(int & x_max, int & y_max, int & x_min, int & y_min);
+
+ /* Frame rate */
+ void setFPS(int fps);
+ int getFPS();
+
+ void allocBuffers();
+ unsigned char * getY();
+ unsigned char * getU();
+ unsigned char * getV();
+ unsigned char * getColorBuffer();
+
+ void registerCallback(WPF *fp, void *ud);
+
+ int start_capturing(char *errmsg);
+ int stop_capturing(char *errmsg);
+ static void newFrame(int fd, void *p);
+
+ void enumerate_ctrl (void);
+ void enumerate_menu (void);
+ int queryINTControls(INumberVectorProperty *nvp);
+ int setINTControl(unsigned int ctrl_id, double new_value, char *errmsg);
+
+ int query_ctrl(unsigned int ctrl_id, double & ctrl_min, double & ctrl_max, double & ctrl_step, double & ctrl_value, char *errmsg);
+
+ protected:
+
+ int xioctl(int fd, int request, void *arg);
+ int read_frame(char *errsg);
+ int uninit_device(char *errmsg);
+ int open_device(const char *devpath, char *errmsg);
+ int init_device(char *errmsg, int pixelFormat , int width, int height);
+ int init_mmap(char *errmsg);
+ int errno_exit(const char *s, char *errmsg);
+
+ void close_device(void);
+ void init_userp(unsigned int buffer_size);
+ void init_read(unsigned int buffer_size);
+
+ void findMinMax();
+
+ struct v4l2_capability cap;
+ struct v4l2_cropcap cropcap;
+ struct v4l2_crop crop;
+ struct v4l2_format fmt;
+
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_querymenu querymenu;
+
+ WPF *callback;
+ void *uptr;
+ char dev_name[64];
+ io_method io;
+ int fd;
+ struct buffer *buffers;
+ unsigned int n_buffers;
+
+ bool dropFrame;
+
+
+ int frameRate;
+ int xmax, xmin, ymax, ymin;
+ int selectCallBackID;
+ unsigned char * YBuf,*UBuf,*VBuf, *colorBuffer, *rgb24_buffer;
+
+};
+
+#endif
diff --git a/kstars/kstars/indi/webcam/vcvt.h b/kstars/kstars/indi/webcam/vcvt.h
new file mode 100644
index 00000000..9b765b41
--- /dev/null
+++ b/kstars/kstars/indi/webcam/vcvt.h
@@ -0,0 +1,73 @@
+/*
+ (C) 2001 Nemosoft Unv. nemosoft@smcc.demon.nl
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+*/
+
+
+/* 'Viewport' conversion routines. These functions convert from one colour
+ space to another, taking into account that the source image has a smaller
+ size than the view, and is placed inside the view:
+
+ +-------view.x------------+
+ | |
+ | +---image.x---+ |
+ | | | |
+ | | | |
+ | +-------------+ |
+ | |
+ +-------------------------+
+
+ The image should always be smaller than the view. The offset (top-left
+ corner of the image) should be precomputed, so you can place the image
+ anywhere in the view.
+
+ The functions take these parameters:
+ - width image width (in pixels)
+ - height image height (in pixels)
+ - plus view width (in pixels)
+ *src pointer at start of image
+ *dst pointer at offset (!) in view
+*/
+
+
+#ifndef VCVT_H
+#define VCVT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Functions in vcvt_i386.S/vcvt_c.c */
+/* 4:2:0 YUV interlaced to RGB/BGR */
+void vcvt_420i_bgr24(int width, int height, int plus, void *src, void *dst);
+void vcvt_420i_rgb24(int width, int height, int plus, void *src, void *dst);
+void vcvt_420i_bgr32(int width, int height, int plus, void *src, void *dst);
+void vcvt_420i_rgb32(int width, int height, int plus, void *src, void *dst);
+
+
+/* Go from 420i to other yuv formats */
+void vcvt_420i_420p(int width, int height, int plus, void *src, void *dsty, void *dstu, void *dstv);
+void vcvt_420i_yuyv(int width, int height, int plus, void *src, void *dst);
+
+#if 0
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/kstars/kstars/indi/webcam/videodev.h b/kstars/kstars/indi/webcam/videodev.h
new file mode 100644
index 00000000..a5b0aec7
--- /dev/null
+++ b/kstars/kstars/indi/webcam/videodev.h
@@ -0,0 +1,346 @@
+#ifndef __LINUX_VIDEODEV_H
+#define __LINUX_VIDEODEV_H
+
+#define VID_TYPE_CAPTURE 1 /* Can capture */
+#define VID_TYPE_TUNER 2 /* Can tune */
+#define VID_TYPE_TELETEXT 4 /* Does teletext */
+#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */
+#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */
+#define VID_TYPE_CLIPPING 32 /* Can clip */
+#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */
+#define VID_TYPE_SCALES 128 /* Scalable */
+#define VID_TYPE_MONOCHROME 256 /* Monochrome only */
+#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */
+#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */
+#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */
+#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */
+#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */
+
+struct video_capability
+{
+ char name[32];
+ int type;
+ int channels; /* Num channels */
+ int audios; /* Num audio devices */
+ int maxwidth; /* Supported width */
+ int maxheight; /* And height */
+ int minwidth; /* Supported width */
+ int minheight; /* And height */
+};
+
+
+struct video_channel
+{
+ int channel;
+ char name[32];
+ int tuners;
+ unsigned int flags;
+#define VIDEO_VC_TUNER 1 /* Channel has a tuner */
+#define VIDEO_VC_AUDIO 2 /* Channel has audio */
+ unsigned short type;
+#define VIDEO_TYPE_TV 1
+#define VIDEO_TYPE_CAMERA 2
+ unsigned short norm; /* Norm set by channel */
+};
+
+struct video_tuner
+{
+ int tuner;
+ char name[32];
+ unsigned long rangelow, rangehigh; /* Tuner range */
+ unsigned int flags;
+#define VIDEO_TUNER_PAL 1
+#define VIDEO_TUNER_NTSC 2
+#define VIDEO_TUNER_SECAM 4
+#define VIDEO_TUNER_LOW 8 /* Uses KHz not MHz */
+#define VIDEO_TUNER_NORM 16 /* Tuner can set norm */
+#define VIDEO_TUNER_STEREO_ON 128 /* Tuner is seeing stereo */
+#define VIDEO_TUNER_RDS_ON 256 /* Tuner is seeing an RDS datastream */
+#define VIDEO_TUNER_MBS_ON 512 /* Tuner is seeing an MBS datastream */
+ unsigned short mode; /* PAL/NTSC/SECAM/OTHER */
+#define VIDEO_MODE_PAL 0
+#define VIDEO_MODE_NTSC 1
+#define VIDEO_MODE_SECAM 2
+#define VIDEO_MODE_AUTO 3
+ unsigned short signal; /* Signal strength 16bit scale */
+};
+
+struct video_picture
+{
+ unsigned short brightness;
+ unsigned short hue;
+ unsigned short colour;
+ unsigned short contrast;
+ unsigned short whiteness; /* Black and white only */
+ unsigned short depth; /* Capture depth */
+ unsigned short palette; /* Palette in use */
+#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */
+#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */
+#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */
+#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */
+#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */
+#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */
+#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */
+#define VIDEO_PALETTE_YUYV 8
+#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */
+#define VIDEO_PALETTE_YUV420 10
+#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */
+#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */
+#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */
+#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */
+#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */
+#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */
+#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */
+#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */
+};
+
+struct video_audio
+{
+ int audio; /* Audio channel */
+ unsigned short volume; /* If settable */
+ unsigned short bass, treble;
+ unsigned int flags;
+#define VIDEO_AUDIO_MUTE 1
+#define VIDEO_AUDIO_MUTABLE 2
+#define VIDEO_AUDIO_VOLUME 4
+#define VIDEO_AUDIO_BASS 8
+#define VIDEO_AUDIO_TREBLE 16
+#define VIDEO_AUDIO_BALANCE 32
+ char name[16];
+#define VIDEO_SOUND_MONO 1
+#define VIDEO_SOUND_STEREO 2
+#define VIDEO_SOUND_LANG1 4
+#define VIDEO_SOUND_LANG2 8
+ unsigned short mode;
+ unsigned short balance; /* Stereo balance */
+ unsigned short step; /* Step actual volume uses */
+};
+
+struct video_clip
+{
+ int x,y;
+ int width, height;
+ struct video_clip *next; /* For user use/driver use only */
+};
+
+struct video_window
+{
+ unsigned int x,y; /* Position of window */
+ unsigned int width,height; /* Its size */
+ unsigned int chromakey;
+ unsigned int flags;
+ struct video_clip *clips; /* Set only */
+ int clipcount;
+#define VIDEO_WINDOW_INTERLACE 1
+#define VIDEO_WINDOW_CHROMAKEY 16 /* Overlay by chromakey */
+#define VIDEO_CLIP_BITMAP -1
+/* bitmap is 1024x625, a '1' bit represents a clipped pixel */
+#define VIDEO_CLIPMAP_SIZE (128 * 625)
+};
+
+struct video_capture
+{
+ unsigned int x,y; /* Offsets into image */
+ unsigned int width, height; /* Area to capture */
+ unsigned short decimation; /* Decimation divider */
+ unsigned short flags; /* Flags for capture */
+#define VIDEO_CAPTURE_ODD 0 /* Temporal */
+#define VIDEO_CAPTURE_EVEN 1
+};
+
+struct video_buffer
+{
+ void *base;
+ int height,width;
+ int depth;
+ int bytesperline;
+};
+
+struct video_mmap
+{
+ unsigned int frame; /* Frame (0 - n) for double buffer */
+ int height,width;
+ unsigned int format; /* should be VIDEO_PALETTE_* */
+};
+
+struct video_key
+{
+ unsigned char key[8];
+ unsigned int flags;
+};
+
+
+#define VIDEO_MAX_FRAME 32
+
+struct video_mbuf
+{
+ int size; /* Total memory to map */
+ int frames; /* Frames */
+ int offsets[VIDEO_MAX_FRAME];
+};
+
+
+#define VIDEO_NO_UNIT (-1)
+
+
+struct video_unit
+{
+ int video; /* Video minor */
+ int vbi; /* VBI minor */
+ int radio; /* Radio minor */
+ int audio; /* Audio minor */
+ int teletext; /* Teletext minor */
+};
+
+struct vbi_format {
+ unsigned int sampling_rate; /* in Hz */
+ unsigned int samples_per_line;
+ unsigned int sample_format; /* VIDEO_PALETTE_RAW only (1 byte) */
+ int start[2]; /* starting line for each frame */
+ unsigned int count[2]; /* count of lines for each frame */
+ unsigned int flags;
+#define VBI_UNSYNC 1 /* can distingues between top/bottom field */
+#define VBI_INTERLACED 2 /* lines are interlaced */
+};
+
+/* video_info is biased towards hardware mpeg encode/decode */
+/* but it could apply generically to any hardware compressor/decompressor */
+struct video_info
+{
+ unsigned int frame_count; /* frames output since decode/encode began */
+ unsigned int h_size; /* current unscaled horizontal size */
+ unsigned int v_size; /* current unscaled veritcal size */
+ unsigned int smpte_timecode; /* current SMPTE timecode (for current GOP) */
+ unsigned int picture_type; /* current picture type */
+ unsigned int temporal_reference; /* current temporal reference */
+ unsigned char user_data[256]; /* user data last found in compressed stream */
+ /* user_data[0] contains user data flags, user_data[1] has count */
+};
+
+/* generic structure for setting playback modes */
+struct video_play_mode
+{
+ int mode;
+ int p1;
+ int p2;
+};
+
+/* for loading microcode / fpga programming */
+struct video_code
+{
+ char loadwhat[16]; /* name or tag of file being passed */
+ int datasize;
+ unsigned char *data;
+};
+
+#define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */
+#define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */
+#define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */
+#define VIDIOCGTUNER _IOWR('v',4,struct video_tuner) /* Get tuner abilities */
+#define VIDIOCSTUNER _IOW('v',5,struct video_tuner) /* Tune the tuner for the current channel */
+#define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */
+#define VIDIOCSPICT _IOW('v',7,struct video_picture) /* Set picture properties */
+#define VIDIOCCAPTURE _IOW('v',8,int) /* Start, end capture */
+#define VIDIOCGWIN _IOR('v',9, struct video_window) /* Get the video overlay window */
+#define VIDIOCSWIN _IOW('v',10, struct video_window) /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
+#define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */
+#define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */
+#define VIDIOCKEY _IOR('v',13, struct video_key) /* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */
+#define VIDIOCGFREQ _IOR('v',14, unsigned long) /* Set tuner */
+#define VIDIOCSFREQ _IOW('v',15, unsigned long) /* Set tuner */
+#define VIDIOCGAUDIO _IOR('v',16, struct video_audio) /* Get audio info */
+#define VIDIOCSAUDIO _IOW('v',17, struct video_audio) /* Audio source, mute etc */
+#define VIDIOCSYNC _IOW('v',18, int) /* Sync with mmap grabbing */
+#define VIDIOCMCAPTURE _IOW('v',19, struct video_mmap) /* Grab frames */
+#define VIDIOCGMBUF _IOR('v',20, struct video_mbuf) /* Memory map buffer info */
+#define VIDIOCGUNIT _IOR('v',21, struct video_unit) /* Get attached units */
+#define VIDIOCGCAPTURE _IOR('v',22, struct video_capture) /* Get subcapture */
+#define VIDIOCSCAPTURE _IOW('v',23, struct video_capture) /* Set subcapture */
+#define VIDIOCSPLAYMODE _IOW('v',24, struct video_play_mode) /* Set output video mode/feature */
+#define VIDIOCSWRITEMODE _IOW('v',25, int) /* Set write mode */
+#define VIDIOCGPLAYINFO _IOR('v',26, struct video_info) /* Get current playback info from hardware */
+#define VIDIOCSMICROCODE _IOW('v',27, struct video_code) /* Load microcode into hardware */
+#define VIDIOCGVBIFMT _IOR('v',28, struct vbi_format) /* Get VBI information */
+#define VIDIOCSVBIFMT _IOW('v',29, struct vbi_format) /* Set VBI information */
+
+
+#define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */
+
+/* VIDIOCSWRITEMODE */
+#define VID_WRITE_MPEG_AUD 0
+#define VID_WRITE_MPEG_VID 1
+#define VID_WRITE_OSD 2
+#define VID_WRITE_TTX 3
+#define VID_WRITE_CC 4
+#define VID_WRITE_MJPEG 5
+
+/* VIDIOCSPLAYMODE */
+#define VID_PLAY_VID_OUT_MODE 0
+ /* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */
+#define VID_PLAY_GENLOCK 1
+ /* p1: 0 = OFF, 1 = ON */
+ /* p2: GENLOCK FINE DELAY value */
+#define VID_PLAY_NORMAL 2
+#define VID_PLAY_PAUSE 3
+#define VID_PLAY_SINGLE_FRAME 4
+#define VID_PLAY_FAST_FORWARD 5
+#define VID_PLAY_SLOW_MOTION 6
+#define VID_PLAY_IMMEDIATE_NORMAL 7
+#define VID_PLAY_SWITCH_CHANNELS 8
+#define VID_PLAY_FREEZE_FRAME 9
+#define VID_PLAY_STILL_MODE 10
+#define VID_PLAY_MASTER_MODE 11
+ /* p1: see below */
+#define VID_PLAY_MASTER_NONE 1
+#define VID_PLAY_MASTER_VIDEO 2
+#define VID_PLAY_MASTER_AUDIO 3
+#define VID_PLAY_ACTIVE_SCANLINES 12
+ /* p1 = first active; p2 = last active */
+#define VID_PLAY_RESET 13
+#define VID_PLAY_END_MARK 14
+
+
+
+#define VID_HARDWARE_BT848 1
+#define VID_HARDWARE_QCAM_BW 2
+#define VID_HARDWARE_PMS 3
+#define VID_HARDWARE_QCAM_C 4
+#define VID_HARDWARE_PSEUDO 5
+#define VID_HARDWARE_SAA5249 6
+#define VID_HARDWARE_AZTECH 7
+#define VID_HARDWARE_SF16MI 8
+#define VID_HARDWARE_RTRACK 9
+#define VID_HARDWARE_ZOLTRIX 10
+#define VID_HARDWARE_SAA7146 11
+#define VID_HARDWARE_VIDEUM 12 /* Reserved for Winnov videum */
+#define VID_HARDWARE_RTRACK2 13
+#define VID_HARDWARE_PERMEDIA2 14 /* Reserved for Permedia2 */
+#define VID_HARDWARE_RIVA128 15 /* Reserved for RIVA 128 */
+#define VID_HARDWARE_PLANB 16 /* PowerMac motherboard video-in */
+#define VID_HARDWARE_BROADWAY 17 /* Broadway project */
+#define VID_HARDWARE_GEMTEK 18
+#define VID_HARDWARE_TYPHOON 19
+#define VID_HARDWARE_VINO 20 /* SGI Indy Vino */
+#define VID_HARDWARE_CADET 21 /* Cadet radio */
+#define VID_HARDWARE_TRUST 22 /* Trust FM Radio */
+#define VID_HARDWARE_TERRATEC 23 /* TerraTec ActiveRadio */
+#define VID_HARDWARE_CPIA 24
+#define VID_HARDWARE_ZR36120 25 /* Zoran ZR36120/ZR36125 */
+#define VID_HARDWARE_ZR36067 26 /* Zoran ZR36067/36060 */
+#define VID_HARDWARE_OV511 27
+#define VID_HARDWARE_ZR356700 28 /* Zoran 36700 series */
+#define VID_HARDWARE_W9966 29
+#define VID_HARDWARE_SE401 30 /* SE401 USB webcams */
+#define VID_HARDWARE_PWC 31 /* Philips webcams */
+#define VID_HARDWARE_MEYE 32 /* Sony Vaio MotionEye cameras */
+#define VID_HARDWARE_CPIA2 33
+#define VID_HARDWARE_VICAM 34
+#define VID_HARDWARE_SF16FMR2 35
+#define VID_HARDWARE_W9968CF 36
+#endif /* __LINUX_VIDEODEV_H */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/kstars/kstars/indi/webcam/videodev2.h b/kstars/kstars/indi/webcam/videodev2.h
new file mode 100644
index 00000000..e3dab3a6
--- /dev/null
+++ b/kstars/kstars/indi/webcam/videodev2.h
@@ -0,0 +1,903 @@
+#ifndef __LINUX_VIDEODEV2_H
+#define __LINUX_VIDEODEV2_H
+/*
+ * Video for Linux Two
+ *
+ * Header file for v4l or V4L2 drivers and applications, for
+ * Linux kernels 2.2.x or 2.4.x.
+ *
+ * See http://bytesex.org/v4l/ for API specs and other
+ * v4l2 documentation.
+ *
+ * Author: Bill Dirks <bdirks@pacbell.net>
+ * Justin Schoeman
+ * et al.
+ */
+/*
+ * M I S C E L L A N E O U S
+ */
+
+/* Four-character-code (FOURCC) */
+#define v4l2_fourcc(a,b,c,d)\
+ (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
+
+/*
+ * E N U M S
+ */
+enum v4l2_field {
+ V4L2_FIELD_ANY = 0, /* driver can choose from none,
+ top, bottom, interlaced
+ depending on whatever it thinks
+ is approximate ... */
+ V4L2_FIELD_NONE = 1, /* this device has no fields ... */
+ V4L2_FIELD_TOP = 2, /* top field only */
+ V4L2_FIELD_BOTTOM = 3, /* bottom field only */
+ V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */
+ V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one
+ buffer, top-bottom order */
+ V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */
+ V4L2_FIELD_ALTERNATE = 7 /* both fields alternating into
+ separate buffers */
+};
+#define V4L2_FIELD_HAS_TOP(field) \
+ ((field) == V4L2_FIELD_TOP ||\
+ (field) == V4L2_FIELD_INTERLACED ||\
+ (field) == V4L2_FIELD_SEQ_TB ||\
+ (field) == V4L2_FIELD_SEQ_BT)
+#define V4L2_FIELD_HAS_BOTTOM(field) \
+ ((field) == V4L2_FIELD_BOTTOM ||\
+ (field) == V4L2_FIELD_INTERLACED ||\
+ (field) == V4L2_FIELD_SEQ_TB ||\
+ (field) == V4L2_FIELD_SEQ_BT)
+#define V4L2_FIELD_HAS_BOTH(field) \
+ ((field) == V4L2_FIELD_INTERLACED ||\
+ (field) == V4L2_FIELD_SEQ_TB ||\
+ (field) == V4L2_FIELD_SEQ_BT)
+
+enum v4l2_buf_type {
+ V4L2_BUF_TYPE_VIDEO_CAPTURE = 1,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT = 2,
+ V4L2_BUF_TYPE_VIDEO_OVERLAY = 3,
+ V4L2_BUF_TYPE_VBI_CAPTURE = 4,
+ V4L2_BUF_TYPE_VBI_OUTPUT = 5,
+ V4L2_BUF_TYPE_PRIVATE = 0x80
+};
+
+enum v4l2_ctrl_type {
+ V4L2_CTRL_TYPE_INTEGER = 1,
+ V4L2_CTRL_TYPE_BOOLEAN = 2,
+ V4L2_CTRL_TYPE_MENU = 3,
+ V4L2_CTRL_TYPE_BUTTON = 4
+};
+
+enum v4l2_tuner_type {
+ V4L2_TUNER_RADIO = 1,
+ V4L2_TUNER_ANALOG_TV = 2
+};
+
+enum v4l2_memory {
+ V4L2_MEMORY_MMAP = 1,
+ V4L2_MEMORY_USERPTR = 2,
+ V4L2_MEMORY_OVERLAY = 3
+};
+
+/* see also http://vektor.theorem.ca/graphics/ycbcr/ */
+enum v4l2_colorspace {
+ /* ITU-R 601 -- broadcast NTSC/PAL */
+ V4L2_COLORSPACE_SMPTE170M = 1,
+
+ /* 1125-Line (US) HDTV */
+ V4L2_COLORSPACE_SMPTE240M = 2,
+
+ /* HD and modern captures. */
+ V4L2_COLORSPACE_REC709 = 3,
+
+ /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */
+ V4L2_COLORSPACE_BT878 = 4,
+
+ /* These should be useful. Assume 601 extents. */
+ V4L2_COLORSPACE_470_SYSTEM_M = 5,
+ V4L2_COLORSPACE_470_SYSTEM_BG = 6,
+
+ /* I know there will be cameras that send this. So, this is
+ * unspecified chromaticities and full 0-255 on each of the
+ * Y'CbCr components
+ */
+ V4L2_COLORSPACE_JPEG = 7,
+
+ /* For RGB colourspaces, this is probably a good start. */
+ V4L2_COLORSPACE_SRGB = 8
+};
+
+enum v4l2_priority {
+ V4L2_PRIORITY_UNSET = 0, /* not initialized */
+ V4L2_PRIORITY_BACKGROUND = 1,
+ V4L2_PRIORITY_INTERACTIVE = 2,
+ V4L2_PRIORITY_RECORD = 3,
+ V4L2_PRIORITY_DEFAULT = V4L2_PRIORITY_INTERACTIVE
+};
+
+struct v4l2_rect {
+ __s32 left;
+ __s32 top;
+ __s32 width;
+ __s32 height;
+};
+
+struct v4l2_fract {
+ __u32 numerator;
+ __u32 denominator;
+};
+
+/*
+ * D R I V E R C A P A B I L I T I E S
+ */
+struct v4l2_capability
+{
+ __u8 driver[16]; /* i.e. "bttv" */
+ __u8 card[32]; /* i.e. "Hauppauge WinTV" */
+ __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */
+ __u32 version; /* should use KERNEL_VERSION() */
+ __u32 capabilities; /* Device capabilities */
+ __u32 reserved[4];
+};
+
+/* Values for 'capabilities' field */
+#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */
+#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */
+#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */
+#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a VBI capture device */
+#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a VBI output device */
+#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */
+
+#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
+#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
+#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */
+
+#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */
+#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */
+#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */
+
+/*
+ * V I D E O I M A G E F O R M A T
+ */
+
+struct v4l2_pix_format
+{
+ __u32 width;
+ __u32 height;
+ __u32 pixelformat;
+ enum v4l2_field field;
+ __u32 bytesperline; /* for padding, zero if unused */
+ __u32 sizeimage;
+ enum v4l2_colorspace colorspace;
+ __u32 priv; /* private data, depends on pixelformat */
+};
+
+/* Pixel format FOURCC depth Description */
+#define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R','G','B','1') /* 8 RGB-3-3-2 */
+#define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R','G','B','O') /* 16 RGB-5-5-5 */
+#define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R','G','B','P') /* 16 RGB-5-6-5 */
+#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R','G','B','Q') /* 16 RGB-5-5-5 BE */
+#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R','G','B','R') /* 16 RGB-5-6-5 BE */
+#define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B','G','R','3') /* 24 BGR-8-8-8 */
+#define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R','G','B','3') /* 24 RGB-8-8-8 */
+#define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */
+#define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */
+#define V4L2_PIX_FMT_GREY v4l2_fourcc('G','R','E','Y') /* 8 Greyscale */
+#define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */
+#define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */
+#define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y','U','Y','V') /* 16 YUV 4:2:2 */
+#define V4L2_PIX_FMT_UYVY v4l2_fourcc('U','Y','V','Y') /* 16 YUV 4:2:2 */
+#define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4','2','2','P') /* 16 YVU422 planar */
+#define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4','1','1','P') /* 16 YVU411 planar */
+#define V4L2_PIX_FMT_Y41P v4l2_fourcc('Y','4','1','P') /* 12 YUV 4:1:1 */
+
+/* two planes -- one Y, one Cr + Cb interleaved */
+#define V4L2_PIX_FMT_NV12 v4l2_fourcc('N','V','1','2') /* 12 Y/CbCr 4:2:0 */
+#define V4L2_PIX_FMT_NV21 v4l2_fourcc('N','V','2','1') /* 12 Y/CrCb 4:2:0 */
+
+/* The following formats are not defined in the V4L2 specification */
+#define V4L2_PIX_FMT_YUV410 v4l2_fourcc('Y','U','V','9') /* 9 YUV 4:1:0 */
+#define V4L2_PIX_FMT_YUV420 v4l2_fourcc('Y','U','1','2') /* 12 YUV 4:2:0 */
+#define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */
+#define V4L2_PIX_FMT_HI240 v4l2_fourcc('H','I','2','4') /* 8 8-bit color */
+
+/* see http://www.siliconimaging.com/RGB%20Bayer.htm */
+#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */
+
+/* compressed formats */
+#define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M','J','P','G') /* Motion-JPEG */
+#define V4L2_PIX_FMT_JPEG v4l2_fourcc('J','P','E','G') /* JFIF JPEG */
+#define V4L2_PIX_FMT_DV v4l2_fourcc('d','v','s','d') /* 1394 */
+#define V4L2_PIX_FMT_MPEG v4l2_fourcc('M','P','E','G') /* MPEG */
+
+/* Vendor-specific formats */
+#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W','N','V','A') /* Winnov hw compress */
+
+/*
+ * F O R M A T E N U M E R A T I O N
+ */
+struct v4l2_fmtdesc
+{
+ __u32 index; /* Format number */
+ enum v4l2_buf_type type; /* buffer type */
+ __u32 flags;
+ __u8 description[32]; /* Description string */
+ __u32 pixelformat; /* Format fourcc */
+ __u32 reserved[4];
+};
+
+#define V4L2_FMT_FLAG_COMPRESSED 0x0001
+
+
+/*
+ * T I M E C O D E
+ */
+struct v4l2_timecode
+{
+ __u32 type;
+ __u32 flags;
+ __u8 frames;
+ __u8 seconds;
+ __u8 minutes;
+ __u8 hours;
+ __u8 userbits[4];
+};
+
+/* Type */
+#define V4L2_TC_TYPE_24FPS 1
+#define V4L2_TC_TYPE_25FPS 2
+#define V4L2_TC_TYPE_30FPS 3
+#define V4L2_TC_TYPE_50FPS 4
+#define V4L2_TC_TYPE_60FPS 5
+
+/* Flags */
+#define V4L2_TC_FLAG_DROPFRAME 0x0001 /* "drop-frame" mode */
+#define V4L2_TC_FLAG_COLORFRAME 0x0002
+#define V4L2_TC_USERBITS_field 0x000C
+#define V4L2_TC_USERBITS_USERDEFINED 0x0000
+#define V4L2_TC_USERBITS_8BITCHARS 0x0008
+/* The above is based on SMPTE timecodes */
+
+
+/*
+ * C O M P R E S S I O N P A R A M E T E R S
+ */
+#if 0
+/* ### generic compression settings don't work, there is too much
+ * ### codec-specific stuff. Maybe reuse that for MPEG codec settings
+ * ### later ... */
+struct v4l2_compression
+{
+ __u32 quality;
+ __u32 keyframerate;
+ __u32 pframerate;
+ __u32 reserved[5];
+
+/* what we'll need for MPEG, extracted from some postings on
+ the v4l list (Gert Vervoort, PlasmaJohn).
+
+system stream:
+ - type: elementary stream(ES), packatised elementary stream(s) (PES)
+ program stream(PS), transport stream(TS)
+ - system bitrate
+ - PS packet size (DVD: 2048 bytes, VCD: 2324 bytes)
+ - TS video PID
+ - TS audio PID
+ - TS PCR PID
+ - TS system information tables (PAT, PMT, CAT, NIT and SIT)
+ - (MPEG-1 systems stream vs. MPEG-2 program stream (TS not supported
+ by MPEG-1 systems)
+
+audio:
+ - type: MPEG (+Layer I,II,III), AC-3, LPCM
+ - bitrate
+ - sampling frequency (DVD: 48 Khz, VCD: 44.1 KHz, 32 kHz)
+ - Trick Modes? (ff, rew)
+ - Copyright
+ - Inverse Telecine
+
+video:
+ - picturesize (SIF, 1/2 D1, 2/3 D1, D1) and PAL/NTSC norm can be set
+ through excisting V4L2 controls
+ - noise reduction, parameters encoder specific?
+ - MPEG video version: MPEG-1, MPEG-2
+ - GOP (Group Of Pictures) definition:
+ - N: number of frames per GOP
+ - M: distance between reference (I,P) frames
+ - open/closed GOP
+ - quantiser matrix: inter Q matrix (64 bytes) and intra Q matrix (64 bytes)
+ - quantiser scale: linear or logarithmic
+ - scanning: alternate or zigzag
+ - bitrate mode: CBR (constant bitrate) or VBR (variable bitrate).
+ - target video bitrate for CBR
+ - target video bitrate for VBR
+ - maximum video bitrate for VBR - min. quantiser value for VBR
+ - max. quantiser value for VBR
+ - adaptive quantisation value
+ - return the number of bytes per GOP or bitrate for bitrate monitoring
+
+*/
+};
+#endif
+
+struct v4l2_jpegcompression
+{
+ int quality;
+
+ int APPn; /* Number of APP segment to be written,
+ * must be 0..15 */
+ int APP_len; /* Length of data in JPEG APPn segment */
+ char APP_data[60]; /* Data in the JPEG APPn segment. */
+
+ int COM_len; /* Length of data in JPEG COM segment */
+ char COM_data[60]; /* Data in JPEG COM segment */
+
+ __u32 jpeg_markers; /* Which markers should go into the JPEG
+ * output. Unless you exactly know what
+ * you do, leave them untouched.
+ * Inluding less markers will make the
+ * resulting code smaller, but there will
+ * be fewer aplications which can read it.
+ * The presence of the APP and COM marker
+ * is influenced by APP_len and COM_len
+ * ONLY, not by this property! */
+
+#define V4L2_JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */
+#define V4L2_JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */
+#define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */
+#define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */
+#define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will
+ * allways use APP0 */
+};
+
+
+/*
+ * M E M O R Y - M A P P I N G B U F F E R S
+ */
+struct v4l2_requestbuffers
+{
+ __u32 count;
+ enum v4l2_buf_type type;
+ enum v4l2_memory memory;
+ __u32 reserved[2];
+};
+
+struct v4l2_buffer
+{
+ __u32 index;
+ enum v4l2_buf_type type;
+ __u32 bytesused;
+ __u32 flags;
+ enum v4l2_field field;
+ struct timeval timestamp;
+ struct v4l2_timecode timecode;
+ __u32 sequence;
+
+ /* memory location */
+ enum v4l2_memory memory;
+ union {
+ __u32 offset;
+ unsigned long userptr;
+ } m;
+ __u32 length;
+ __u32 input;
+ __u32 reserved;
+};
+
+/* Flags for 'flags' field */
+#define V4L2_BUF_FLAG_MAPPED 0x0001 /* Buffer is mapped (flag) */
+#define V4L2_BUF_FLAG_QUEUED 0x0002 /* Buffer is queued for processing */
+#define V4L2_BUF_FLAG_DONE 0x0004 /* Buffer is ready */
+#define V4L2_BUF_FLAG_KEYFRAME 0x0008 /* Image is a keyframe (I-frame) */
+#define V4L2_BUF_FLAG_PFRAME 0x0010 /* Image is a P-frame */
+#define V4L2_BUF_FLAG_BFRAME 0x0020 /* Image is a B-frame */
+#define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */
+#define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */
+
+/*
+ * O V E R L A Y P R E V I E W
+ */
+struct v4l2_framebuffer
+{
+ __u32 capability;
+ __u32 flags;
+/* FIXME: in theory we should pass something like PCI device + memory
+ * region + offset instead of some physical address */
+ void* base;
+ struct v4l2_pix_format fmt;
+};
+/* Flags for the 'capability' field. Read only */
+#define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001
+#define V4L2_FBUF_CAP_CHROMAKEY 0x0002
+#define V4L2_FBUF_CAP_LIST_CLIPPING 0x0004
+#define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008
+/* Flags for the 'flags' field. */
+#define V4L2_FBUF_FLAG_PRIMARY 0x0001
+#define V4L2_FBUF_FLAG_OVERLAY 0x0002
+#define V4L2_FBUF_FLAG_CHROMAKEY 0x0004
+
+struct v4l2_clip
+{
+ struct v4l2_rect c;
+ struct v4l2_clip *next;
+};
+
+struct v4l2_window
+{
+ struct v4l2_rect w;
+ enum v4l2_field field;
+ __u32 chromakey;
+ struct v4l2_clip *clips;
+ __u32 clipcount;
+ void *bitmap;
+};
+
+
+/*
+ * C A P T U R E P A R A M E T E R S
+ */
+struct v4l2_captureparm
+{
+ __u32 capability; /* Supported modes */
+ __u32 capturemode; /* Current mode */
+ struct v4l2_fract timeperframe; /* Time per frame in .1us units */
+ __u32 extendedmode; /* Driver-specific extensions */
+ __u32 readbuffers; /* # of buffers for read */
+ __u32 reserved[4];
+};
+/* Flags for 'capability' and 'capturemode' fields */
+#define V4L2_MODE_HIGHQUALITY 0x0001 /* High quality imaging mode */
+#define V4L2_CAP_TIMEPERFRAME 0x1000 /* timeperframe field is supported */
+
+struct v4l2_outputparm
+{
+ __u32 capability; /* Supported modes */
+ __u32 outputmode; /* Current mode */
+ struct v4l2_fract timeperframe; /* Time per frame in seconds */
+ __u32 extendedmode; /* Driver-specific extensions */
+ __u32 writebuffers; /* # of buffers for write */
+ __u32 reserved[4];
+};
+
+/*
+ * I N P U T I M A G E C R O P P I N G
+ */
+
+struct v4l2_cropcap {
+ enum v4l2_buf_type type;
+ struct v4l2_rect bounds;
+ struct v4l2_rect defrect;
+ struct v4l2_fract pixelaspect;
+};
+
+struct v4l2_crop {
+ enum v4l2_buf_type type;
+ struct v4l2_rect c;
+};
+
+/*
+ * A N A L O G V I D E O S T A N D A R D
+ */
+
+typedef __u64 v4l2_std_id;
+
+/* one bit for each */
+#define V4L2_STD_PAL_B ((v4l2_std_id)0x00000001)
+#define V4L2_STD_PAL_B1 ((v4l2_std_id)0x00000002)
+#define V4L2_STD_PAL_G ((v4l2_std_id)0x00000004)
+#define V4L2_STD_PAL_H ((v4l2_std_id)0x00000008)
+#define V4L2_STD_PAL_I ((v4l2_std_id)0x00000010)
+#define V4L2_STD_PAL_D ((v4l2_std_id)0x00000020)
+#define V4L2_STD_PAL_D1 ((v4l2_std_id)0x00000040)
+#define V4L2_STD_PAL_K ((v4l2_std_id)0x00000080)
+
+#define V4L2_STD_PAL_M ((v4l2_std_id)0x00000100)
+#define V4L2_STD_PAL_N ((v4l2_std_id)0x00000200)
+#define V4L2_STD_PAL_Nc ((v4l2_std_id)0x00000400)
+#define V4L2_STD_PAL_60 ((v4l2_std_id)0x00000800)
+
+#define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000)
+#define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000)
+
+#define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000)
+#define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000)
+#define V4L2_STD_SECAM_G ((v4l2_std_id)0x00040000)
+#define V4L2_STD_SECAM_H ((v4l2_std_id)0x00080000)
+#define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000)
+#define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000)
+#define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000)
+
+/* ATSC/HDTV */
+#define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000)
+#define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000)
+
+/* some common needed stuff */
+#define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\
+ V4L2_STD_PAL_B1 |\
+ V4L2_STD_PAL_G)
+#define V4L2_STD_PAL_DK (V4L2_STD_PAL_D |\
+ V4L2_STD_PAL_D1 |\
+ V4L2_STD_PAL_K)
+#define V4L2_STD_PAL (V4L2_STD_PAL_BG |\
+ V4L2_STD_PAL_DK |\
+ V4L2_STD_PAL_H |\
+ V4L2_STD_PAL_I)
+#define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\
+ V4L2_STD_NTSC_M_JP)
+#define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\
+ V4L2_STD_SECAM_K |\
+ V4L2_STD_SECAM_K1)
+#define V4L2_STD_SECAM (V4L2_STD_SECAM_B |\
+ V4L2_STD_SECAM_G |\
+ V4L2_STD_SECAM_H |\
+ V4L2_STD_SECAM_DK |\
+ V4L2_STD_SECAM_L)
+
+#define V4L2_STD_525_60 (V4L2_STD_PAL_M |\
+ V4L2_STD_PAL_60 |\
+ V4L2_STD_NTSC)
+#define V4L2_STD_625_50 (V4L2_STD_PAL |\
+ V4L2_STD_PAL_N |\
+ V4L2_STD_PAL_Nc |\
+ V4L2_STD_SECAM)
+#define V4L2_STD_ATSC (V4L2_STD_ATSC_8_VSB |\
+ V4L2_STD_ATSC_16_VSB)
+
+#define V4L2_STD_UNKNOWN 0
+#define V4L2_STD_ALL (V4L2_STD_525_60 |\
+ V4L2_STD_625_50)
+
+struct v4l2_standard
+{
+ __u32 index;
+ v4l2_std_id id;
+ __u8 name[24];
+ struct v4l2_fract frameperiod; /* Frames, not fields */
+ __u32 framelines;
+ __u32 reserved[4];
+};
+
+
+/*
+ * V I D E O I N P U T S
+ */
+struct v4l2_input
+{
+ __u32 index; /* Which input */
+ __u8 name[32]; /* Label */
+ __u32 type; /* Type of input */
+ __u32 audioset; /* Associated audios (bitfield) */
+ __u32 tuner; /* Associated tuner */
+ v4l2_std_id std;
+ __u32 status;
+ __u32 reserved[4];
+};
+/* Values for the 'type' field */
+#define V4L2_INPUT_TYPE_TUNER 1
+#define V4L2_INPUT_TYPE_CAMERA 2
+
+/* field 'status' - general */
+#define V4L2_IN_ST_NO_POWER 0x00000001 /* Attached device is off */
+#define V4L2_IN_ST_NO_SIGNAL 0x00000002
+#define V4L2_IN_ST_NO_COLOR 0x00000004
+
+/* field 'status' - analog */
+#define V4L2_IN_ST_NO_H_LOCK 0x00000100 /* No horizontal sync lock */
+#define V4L2_IN_ST_COLOR_KILL 0x00000200 /* Color killer is active */
+
+/* field 'status' - digital */
+#define V4L2_IN_ST_NO_SYNC 0x00010000 /* No synchronization lock */
+#define V4L2_IN_ST_NO_EQU 0x00020000 /* No equalizer lock */
+#define V4L2_IN_ST_NO_CARRIER 0x00040000 /* Carrier recovery failed */
+
+/* field 'status' - VCR and set-top box */
+#define V4L2_IN_ST_MACROVISION 0x01000000 /* Macrovision detected */
+#define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */
+#define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */
+
+/*
+ * V I D E O O U T P U T S
+ */
+struct v4l2_output
+{
+ __u32 index; /* Which output */
+ __u8 name[32]; /* Label */
+ __u32 type; /* Type of output */
+ __u32 audioset; /* Associated audios (bitfield) */
+ __u32 modulator; /* Associated modulator */
+ v4l2_std_id std;
+ __u32 reserved[4];
+};
+/* Values for the 'type' field */
+#define V4L2_OUTPUT_TYPE_MODULATOR 1
+#define V4L2_OUTPUT_TYPE_ANALOG 2
+#define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3
+
+/*
+ * C O N T R O L S
+ */
+struct v4l2_control
+{
+ __u32 id;
+ __s32 value;
+};
+
+/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
+struct v4l2_queryctrl
+{
+ __u32 id;
+ enum v4l2_ctrl_type type;
+ __u8 name[32]; /* Whatever */
+ __s32 minimum; /* Note signedness */
+ __s32 maximum;
+ __s32 step;
+ __s32 default_value;
+ __u32 flags;
+ __u32 reserved[2];
+};
+
+/* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */
+struct v4l2_querymenu
+{
+ __u32 id;
+ __u32 index;
+ __u8 name[32]; /* Whatever */
+ __u32 reserved;
+};
+
+/* Control flags */
+#define V4L2_CTRL_FLAG_DISABLED 0x0001
+#define V4L2_CTRL_FLAG_GRABBED 0x0002
+
+/* Control IDs defined by V4L2 */
+#define V4L2_CID_BASE 0x00980900
+/* IDs reserved for driver specific controls */
+#define V4L2_CID_PRIVATE_BASE 0x08000000
+
+#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0)
+#define V4L2_CID_CONTRAST (V4L2_CID_BASE+1)
+#define V4L2_CID_SATURATION (V4L2_CID_BASE+2)
+#define V4L2_CID_HUE (V4L2_CID_BASE+3)
+#define V4L2_CID_AUDIO_VOLUME (V4L2_CID_BASE+5)
+#define V4L2_CID_AUDIO_BALANCE (V4L2_CID_BASE+6)
+#define V4L2_CID_AUDIO_BASS (V4L2_CID_BASE+7)
+#define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8)
+#define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9)
+#define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10)
+#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11)
+#define V4L2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12)
+#define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13)
+#define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14)
+#define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15)
+#define V4L2_CID_GAMMA (V4L2_CID_BASE+16)
+#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* ? Not sure */
+#define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17)
+#define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18)
+#define V4L2_CID_GAIN (V4L2_CID_BASE+19)
+#define V4L2_CID_HFLIP (V4L2_CID_BASE+20)
+#define V4L2_CID_VFLIP (V4L2_CID_BASE+21)
+#define V4L2_CID_HCENTER (V4L2_CID_BASE+22)
+#define V4L2_CID_VCENTER (V4L2_CID_BASE+23)
+#define V4L2_CID_LASTP1 (V4L2_CID_BASE+24) /* last CID + 1 */
+
+/*
+ * T U N I N G
+ */
+struct v4l2_tuner
+{
+ __u32 index;
+ __u8 name[32];
+ enum v4l2_tuner_type type;
+ __u32 capability;
+ __u32 rangelow;
+ __u32 rangehigh;
+ __u32 rxsubchans;
+ __u32 audmode;
+ __s32 signal;
+ __s32 afc;
+ __u32 reserved[4];
+};
+
+struct v4l2_modulator
+{
+ __u32 index;
+ __u8 name[32];
+ __u32 capability;
+ __u32 rangelow;
+ __u32 rangehigh;
+ __u32 txsubchans;
+ __u32 reserved[4];
+};
+
+/* Flags for the 'capability' field */
+#define V4L2_TUNER_CAP_LOW 0x0001
+#define V4L2_TUNER_CAP_NORM 0x0002
+#define V4L2_TUNER_CAP_STEREO 0x0010
+#define V4L2_TUNER_CAP_LANG2 0x0020
+#define V4L2_TUNER_CAP_SAP 0x0020
+#define V4L2_TUNER_CAP_LANG1 0x0040
+
+/* Flags for the 'rxsubchans' field */
+#define V4L2_TUNER_SUB_MONO 0x0001
+#define V4L2_TUNER_SUB_STEREO 0x0002
+#define V4L2_TUNER_SUB_LANG2 0x0004
+#define V4L2_TUNER_SUB_SAP 0x0004
+#define V4L2_TUNER_SUB_LANG1 0x0008
+
+/* Values for the 'audmode' field */
+#define V4L2_TUNER_MODE_MONO 0x0000
+#define V4L2_TUNER_MODE_STEREO 0x0001
+#define V4L2_TUNER_MODE_LANG2 0x0002
+#define V4L2_TUNER_MODE_SAP 0x0002
+#define V4L2_TUNER_MODE_LANG1 0x0003
+
+struct v4l2_frequency
+{
+ __u32 tuner;
+ enum v4l2_tuner_type type;
+ __u32 frequency;
+ __u32 reserved[8];
+};
+
+/*
+ * A U D I O
+ */
+struct v4l2_audio
+{
+ __u32 index;
+ __u8 name[32];
+ __u32 capability;
+ __u32 mode;
+ __u32 reserved[2];
+};
+/* Flags for the 'capability' field */
+#define V4L2_AUDCAP_STEREO 0x00001
+#define V4L2_AUDCAP_AVL 0x00002
+
+/* Flags for the 'mode' field */
+#define V4L2_AUDMODE_AVL 0x00001
+
+struct v4l2_audioout
+{
+ __u32 index;
+ __u8 name[32];
+ __u32 capability;
+ __u32 mode;
+ __u32 reserved[2];
+};
+
+/*
+ * D A T A S E R V I C E S ( V B I )
+ *
+ * Data services API by Michael Schimek
+ */
+
+struct v4l2_vbi_format
+{
+ __u32 sampling_rate; /* in 1 Hz */
+ __u32 offset;
+ __u32 samples_per_line;
+ __u32 sample_format; /* V4L2_PIX_FMT_* */
+ __s32 start[2];
+ __u32 count[2];
+ __u32 flags; /* V4L2_VBI_* */
+ __u32 reserved[2]; /* must be zero */
+};
+
+/* VBI flags */
+#define V4L2_VBI_UNSYNC (1<< 0)
+#define V4L2_VBI_INTERLACED (1<< 1)
+
+
+/*
+ * A G G R E G A T E S T R U C T U R E S
+ */
+
+/* Stream data format
+ */
+struct v4l2_format
+{
+ enum v4l2_buf_type type;
+ union
+ {
+ struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE
+ struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY
+ struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE
+ __u8 raw_data[200]; // user-defined
+ } fmt;
+};
+
+
+/* Stream type-dependent parameters
+ */
+struct v4l2_streamparm
+{
+ enum v4l2_buf_type type;
+ union
+ {
+ struct v4l2_captureparm capture;
+ struct v4l2_outputparm output;
+ __u8 raw_data[200]; /* user-defined */
+ } parm;
+};
+
+
+
+/*
+ * I O C T L C O D E S F O R V I D E O D E V I C E S
+ *
+ */
+#define VIDIOC_QUERYCAP _IOR ('V', 0, struct v4l2_capability)
+#define VIDIOC_RESERVED _IO ('V', 1)
+#define VIDIOC_ENUM_FMT _IOWR ('V', 2, struct v4l2_fmtdesc)
+#define VIDIOC_G_FMT _IOWR ('V', 4, struct v4l2_format)
+#define VIDIOC_S_FMT _IOWR ('V', 5, struct v4l2_format)
+#if 0
+#define VIDIOC_G_COMP _IOR ('V', 6, struct v4l2_compression)
+#define VIDIOC_S_COMP _IOW ('V', 7, struct v4l2_compression)
+#endif
+#define VIDIOC_REQBUFS _IOWR ('V', 8, struct v4l2_requestbuffers)
+#define VIDIOC_QUERYBUF _IOWR ('V', 9, struct v4l2_buffer)
+#define VIDIOC_G_FBUF _IOR ('V', 10, struct v4l2_framebuffer)
+#define VIDIOC_S_FBUF _IOW ('V', 11, struct v4l2_framebuffer)
+#define VIDIOC_OVERLAY _IOW ('V', 14, int)
+#define VIDIOC_QBUF _IOWR ('V', 15, struct v4l2_buffer)
+#define VIDIOC_DQBUF _IOWR ('V', 17, struct v4l2_buffer)
+#define VIDIOC_STREAMON _IOW ('V', 18, int)
+#define VIDIOC_STREAMOFF _IOW ('V', 19, int)
+#define VIDIOC_G_PARM _IOWR ('V', 21, struct v4l2_streamparm)
+#define VIDIOC_S_PARM _IOWR ('V', 22, struct v4l2_streamparm)
+#define VIDIOC_G_STD _IOR ('V', 23, v4l2_std_id)
+#define VIDIOC_S_STD _IOW ('V', 24, v4l2_std_id)
+#define VIDIOC_ENUMSTD _IOWR ('V', 25, struct v4l2_standard)
+#define VIDIOC_ENUMINPUT _IOWR ('V', 26, struct v4l2_input)
+#define VIDIOC_G_CTRL _IOWR ('V', 27, struct v4l2_control)
+#define VIDIOC_S_CTRL _IOWR ('V', 28, struct v4l2_control)
+#define VIDIOC_G_TUNER _IOWR ('V', 29, struct v4l2_tuner)
+#define VIDIOC_S_TUNER _IOW ('V', 30, struct v4l2_tuner)
+#define VIDIOC_G_AUDIO _IOR ('V', 33, struct v4l2_audio)
+#define VIDIOC_S_AUDIO _IOW ('V', 34, struct v4l2_audio)
+#define VIDIOC_QUERYCTRL _IOWR ('V', 36, struct v4l2_queryctrl)
+#define VIDIOC_QUERYMENU _IOWR ('V', 37, struct v4l2_querymenu)
+#define VIDIOC_G_INPUT _IOR ('V', 38, int)
+#define VIDIOC_S_INPUT _IOWR ('V', 39, int)
+#define VIDIOC_G_OUTPUT _IOR ('V', 46, int)
+#define VIDIOC_S_OUTPUT _IOWR ('V', 47, int)
+#define VIDIOC_ENUMOUTPUT _IOWR ('V', 48, struct v4l2_output)
+#define VIDIOC_G_AUDOUT _IOR ('V', 49, struct v4l2_audioout)
+#define VIDIOC_S_AUDOUT _IOW ('V', 50, struct v4l2_audioout)
+#define VIDIOC_G_MODULATOR _IOWR ('V', 54, struct v4l2_modulator)
+#define VIDIOC_S_MODULATOR _IOW ('V', 55, struct v4l2_modulator)
+#define VIDIOC_G_FREQUENCY _IOWR ('V', 56, struct v4l2_frequency)
+#define VIDIOC_S_FREQUENCY _IOW ('V', 57, struct v4l2_frequency)
+#define VIDIOC_CROPCAP _IOWR ('V', 58, struct v4l2_cropcap)
+#define VIDIOC_G_CROP _IOWR ('V', 59, struct v4l2_crop)
+#define VIDIOC_S_CROP _IOW ('V', 60, struct v4l2_crop)
+#define VIDIOC_G_JPEGCOMP _IOR ('V', 61, struct v4l2_jpegcompression)
+#define VIDIOC_S_JPEGCOMP _IOW ('V', 62, struct v4l2_jpegcompression)
+#define VIDIOC_QUERYSTD _IOR ('V', 63, v4l2_std_id)
+#define VIDIOC_TRY_FMT _IOWR ('V', 64, struct v4l2_format)
+#define VIDIOC_ENUMAUDIO _IOWR ('V', 65, struct v4l2_audio)
+#define VIDIOC_ENUMAUDOUT _IOWR ('V', 66, struct v4l2_audioout)
+#define VIDIOC_G_PRIORITY _IOR ('V', 67, enum v4l2_priority)
+#define VIDIOC_S_PRIORITY _IOW ('V', 68, enum v4l2_priority)
+
+/* for compatibility, will go away some day */
+#define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int)
+#define VIDIOC_S_PARM_OLD _IOW ('V', 22, struct v4l2_streamparm)
+#define VIDIOC_S_CTRL_OLD _IOW ('V', 28, struct v4l2_control)
+#define VIDIOC_G_AUDIO_OLD _IOWR ('V', 33, struct v4l2_audio)
+#define VIDIOC_G_AUDOUT_OLD _IOWR ('V', 49, struct v4l2_audioout)
+#define VIDIOC_CROPCAP_OLD _IOR ('V', 58, struct v4l2_cropcap)
+
+#define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */
+
+#endif /* __LINUX_VIDEODEV2_H */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */