Library and Utilities
for SBIG ST7/ST8/ST5C/ST237
Steve Ashe
ashe@dimensional.com
version 2.4 15 May 2001
1. Installation
a) Untar it
Get the package using anonymous ftp from ftp ftp.dimensional.com/users/ashe/sbig-linux-2.1beta.tar.gz
Make a directory, copy the file into it, and enter tar xvzf sbig-linux-2.1beta.tar.gz
You should be able to run either the 'tester' or 'snapper' programs now, though I recommend reading on...
Link sbig.a into your program. The sample makefile shows one way to do this.
Look ma, no source -- there is source for the sample 'tester' and 'snapper' programs, but NOT for sbig.a -- sorry, but the SBIG protocols are proprietary, and sbig.a was developed under license for the Santa Barbara Instruments Group.
b) The parallel port
The standard parallel port is at IO base address 0x378. This is the default for the sample programs.
Note that Linux 2.0.x numbers parallel ports differently than Linux 2.2.x You don't care how Linux numbers the port, since you are not using the kernel driver to access the port.
If you have only one parallel port and you haven't mucked with it in your PC's BIOS settings, then it will be at address 0x378. Other addresses that are acceptable to sbig-linux are 0x3bc and 0x278. You can specify these with a "-port 0x3bc" (e.g.) to the sample programs.
It would be wise to run a kernel without line-printer support and without IDE devices on the parallel port. If you have a printer on the parallel port, then lpd (or whatever) may query for status and do bad things to the ST7 protocol, especially if it decides to enable interrupts on the parallel port.
If you must share a parallel port with other devices, then one solution is to install the parallel port devices as loadable modules and unload them (using rmmod) before hooking up your CCD camera. If you use RedHat 5.x, then I believe they are built this way.
2. Operational scheme
You program links in sbig.a and must run setuid root (see chmod(1)) or you must be root when running it. The library code requires direct access to gnarly interfaces and hardware which Linux only allows if you're the superuser. Sorry, but such is life.
Your first sbig_ call must be sbig_init().
If the program is not running as root, it will print a message and exit with code 1 at this point. Otherwise, all routines return 0 for success and a negative integer for failure. The error codes are listed in sbig.h, and there is a utility routine (sbig_show_error) that converts them to strings.
The interface to sbig_init() is described below.
Common reasons for failure are:
* the wrong parallel port
* a parallel port with some peculiar mode (set your BIOS to standard
bidirectional)
* cabling snafu
* a program (daemon, especially) that thinks some device other than a
CCD camera is attached to the parallel port. Check /proc/devices for an 'lp driver'. I recommend you compile a kernel without it, or if your kernel installs it as a module (it will show up in the lsmod list in this case), rmmod it.
Note: Linux 2.1.x and 2.2.x has a protocol that handles multiple devices on a parallel and arbitrates between drivers for the port. This driver is not used by the library, and can be removed.
Although the sbig calls can be made at random, while there is a definite sequence for producing an image. First you make a call sbig_expose() call to start an exposure. This call returns immediately. When the exposure is nearly done, you poll for completion using sbig_status(). When it is ready, you retrieve the image using sbig_readout() or sbig_readout2().
The attached 'tester' program should give you some idea of how this works in practice. It will take an exposure and save it as a FITS file. (The common Linux utility 'xv' will read FITS files, FYI). It also allows adjustment of temperature regulation and other Camera stuff. Source code is included, so you may modify it as you wish.
The 'snapper' program is probably the world's simplest image acquisition and processing program. It takes an image or subimage, subtracts a dark it takes, and then normalizes and gamma corrects the image, displaying it in an X window. You probably want to use 'tester' first to set the cooling and adjust the filter wheel. You can start/stop either program without the camera losing track of what its doing. Source code is included, so you may modify it make a full fledged imaging program from it :-)
Note: the snapper program uses Imlib, which is available in the RedHat distributions (among others). You want the Imlib-devel package.
Note: as you may know, the incompatibilities between shared libraries and their utilities has been a nightmare since about 2.0.30. The 'tester' program is a static link, which makes it big, but it doesn't use any shared libraries so you should be able to run it, no matter what. As of this writing, I haven't built a static version of 'snapper,' but I'll try to make one.
3. sbig library calls
for all calls, #include "sbig.h"
a) sbig_init
int sbig_init(int port, int verbosity, struct sbig_init *info_return)
The sbig_init structure is defined in sbig.h as:
struct sbig_init {
/* these are filled in on return... */
float linux_version;
int nmbr_bad_columns;
int bad_columns[4];
int imaging_abg_type;
char serial_number[10];
unsigned firmware_version;
char camera_name[64];
struct camera_info {
int nmbr_readout_modes;
struct readout_mode {
int mode;
int width;
int height;
int gain;
unsigned pixel_width;
unsigned pixel_height;
} readout_mode[12];
} camera_info[2];
int ST5_AD_size;
int ST5_filter_type;
};
This must be the first sbig call.
The first argument is the IO address of the parallel port. You may specify
one of six possibilities here:
1 or 0x378 -- use the standard (DOS lp1:) parallel port
2 or 0x3bc -- use the secondary (DOS lp2:) parallel port
3 or 0x278 -- use the tertiary (DOS lp3:) parallel port
The second argument is a verbosity level. If 0, the library will only return status codes. If 1, then it will print error info (to stdout). If 2, 3, 4 or 5, it prints progressivly more elaborate progress/status information. If you have any trouble at all, set verbosity to 5. For normal use, 1 is recommended.
On return, all other fields are filled in, as follows:
linux_version driver/module version number, currently 2.0
nmbr_bad_columns number of bad columns in the imaging CCD
bad_columns the actual bad columns [numbered from 1???]
imaging_abg_type boolean indicating whether CCD has antibloom gates
serial_number SBIG's camera serial number
firmware_version internal to SBIG
camera_name the model name of the camera
camera_info an array of two structures, the first [?] for the
imaging CCD, and the second for the tracking CCD
readout_mode an array of formats that each CCD supports:
mode the mode id (used to specify a mode)
width height in pixels
gain multiply this by 0.01 to get e-/ADU
pixel_width in nanometers [should be 9000binning]
pixel_height in nanometers [should be 9000binning]
ST5_AD_size number of conversion bits for ST5 type cameras.
0 is not relevant, 1 is 12-bit, 2 is 16-bit.
ST5_filter_type 0 is not relevant, 1 is "external", 2 is "vane",
3 is "filter wheel".
Normal return is 0. If the privleged calls cannot be executed (because you aren't root), then a message is printed to stderr and the program exits. Otherwise, a negative error code (see sbig.h) is returned.
- example
- struct sbig_info info; ret = sbig_init(0x378, 2, &info);
b) sbig_get_status()
int sbig_get_status(struct sbig_status *status_return)
The call fills in a structure with status information. The sbig_status structure is defined in sbig.h as:
struct sbig_status {
int imaging_ccd_status;
int tracking_ccd_status;
int fan_on;
int shutter_state;
int led_state;
int shutter_edge;
int plus_x_relay;
int minus_x_relay;
int plus_y_relay;
int minus_y_relay;
int pulse_active;
int temperature_regulation;
int temperature_setpoint;
int cooling_power;
int air_temperature;
int ccd_temperature;
};
This call can be made at any time. The values returned are:
imaging_ccd_status 0 idle, 2 in progress, or 3 for image complete tracking_ccd_status same, but for tracking CCD fan_on 0 fan is off, 1 fan is on shutter_state 0 open, 1 closed, 2 opening, 3 closing led_state 0 LED is off, 2 slow blink, 3 fast blink shutter_edge 255 indicates shutter failure; all others OK [?] plus_x_relay boolean indicating whether +X relay is active minus_x_relay boolean indicating whether -X relay is active plus_y_relay boolean indicating whether +Y relay is active minus_y_relay boolean indicating whether -Y relay is active
temperature_regulation boolean indicating whether temp regulation is on temperature_setpoint target temperature for regulation, in 0.01 deg C
cooling_power amount of cooling being applied in arbitrary units
from 0 to 255, inclusive
ccd_temperature in units of 0.01 deg C
air_temperature in units of 0.01 deg C
- example
- struct sbig_status status; sbig_status(&status); printf("current ccd temperature is %g\n", 0.1*status.ccd_temperature);
c) sbig_control
Use this call to turn the camera's fan on or off, to control the shutter, or to control the LED on the back of the camera.
int sbig_control(struct sbig_control *control_input)
where sbig.h defines:
struct sbig_control {
int fan_on;
int shutter;
int led;
};
If fan_on is zero, the fan is turned off; otherwise it is turned on.
If shutter is 0, then the shutter state remains unchanged. If 1, the shutter is opened, if 2 it is closed. If 3, the shutter is reinitialized. The shutter should only need to be reinitialized if the shutter_state in the sbig_status() command returns 255.
If led is 0, the LED is turned off. If 1, it is turned on; if 2, it is blinked slowly; if 3, it is blinked rapidly.
- example
- /* turn off the fan and the LED */ struct sbig_control control; control.fan_on = 0; control.shutter = 0; /* don't change */ control.led = 0; ret = sbig_control(&control);
d) sbig_pulse
Use this command to control the pulse motor on the CFW filter wheel.
int sbig_pulse(struct sbig_pulse *pulse_params_input)
where sbig.h defines
struct sbig_pulse {
int nmbr_pulses;
int pulse_width;
int pulse_interval;
};
This generates a train of pulses to the filter wheel motor. Each pulse is between 9 and 255 microseconds in duration, and the interval between pulse rising edges is given by pulse_interval. The shortest interval is (29+pulse_width) microseconds, and the longest is 255 microseconds.
Example, rotate the CFW8 filter wheel:
struct sbig_pulse pulse;
int filter_wheel_position; /* 1 to 5, inclusive */
/* these magic numbers were culled from documentation on the SBIG website */
pulse.pulse_interval = 18270;
pulse.nmbr_pulses = 60;
pulse.pulse_width = 500 + 300*(filter_wheel_position-1);
sbig_pulse(&pulse);
e) sbig_activate_relay()
Use this command to control the guiding "relays".
int sbig_activate_relay(struct sbig_relay *input_params)
where sbig.h defines:
struct sbig_relay {
int x_plus_time;
int x_minus_time;
int y_plus_time;
int y_minus_time;
};
The camera has four virtual relays used for controlling guiding motors. These are independent -- the +X and -X can simultaneously be activated. Each element in sbig_relay determines an activation time in units of 0.01 second. Each call immediately resets the timing for all four relays. A relay is turned off if the time is set to zero.
Use sbig_status() to get the current values of the relays.
f) sbig_expose()
Use this command to begin an exposure. Exposures on the imaging and tracking CCDs are independent and controlled separately.
int sbig_expose(struct sbig_expose *expose_params_input)
where sbig.h defines
struct sbig_expose {
int ccd;
int exposure_time;
int abg_state;
int shutter;
};
This command is issued to start an exposure. The command returns immediately. The sbig_status() can be called to determine when the exposure is completed. The exposed image remains on the camera for some amount [??] of time; it is read using the sbig_readout() command.
The structure elements are specified as: ccd -- which CCD to use for the exposure: 0 for imaging CCD, 1 for
tracking CCD.
exposure_time -- length of the exposure in hundreths of second, allowable
values are between 11 (0.11 sec) and 16777716 (167777.16 sec) for
the imaging CCD and between 11 and 65535 (655.35 sec) for the
tracking CCD.
abg_state -- 0 off, 1 low, 2 medium, 3 high. [untested] shutter -- 0 no change in shutter (i.e. control of shutter using
SBIG_CONTROL command), 1 normal shutter (open during exposure,
closed otherwise), 2 shutter closed (for taking dark frames).
If you have a dual CCD camera, then two exposure can occur at once. Typically you start the imaging CCD exposure, and then expose and readout a number of tracking CCD exposures (with shutter = 0), then the image.
Examples of this call are in tester.c and snapper.c.
g) sbig_readout and sbig_readout2
Use this command to read out a completed exposure. You may read out any subimage of the exposure using a supported binning mode. However, only one sbig_readout call is allowed per exposure.
int sbig_readout(struct sbig_readout *readout_params_input)
where sbig.h defines:
struct sbig_readout {
int ccd;
int binning;
int x, y;
int width, height;
unsigned short data;
int data_size_in_bytes;
int (callback)(float percent_complete);
};
-or-
int sbig_readout2(struct sbig_reaout2 *readout_params_input)
where sbig.h defines
#define SBIG_NO_SHUTTER_DELAY 0x0001 /* don't wait for shutter to close */ struct sbig_readout2 {
int flags; /* see immediately above */
int ccd;
int binning;
int x, y;
int width, height;
unsigned short data;
int data_size_in_bytes;
int (callback)(float percent_complete);
};
This command extracts part or all of the exposed image.
The structure elements specified are:
flags -- 0, or SBIG_NO_SHUTTER_DELAY; if you are reading out the
tracking at a high rate, such as during an AO7-guided exposure,
and are not moving the shutter, set this flag to avoid the
delay put in for the shutter to stablize.
ccd -- which CCD's exposure to read, 0 for imaging, 1 for tracking. binning -- the binning mode to use. The available modes are given
in the sbig_init structure returned from sbig_init(). These
will be: 0, for no binning, 1 for 2x2 on chip, 3 for 3x3 on chip
binning, plus other modes depending on the camera.
x, y -- the lower left corner of the imaging, indexed from zero width, height -- the size of the image in pixels (binned pixels, if
binning is specified in the 'binning' parameter). data -- a pointer to enough memory to hold the image. The data is
16 bits per pixel, contiguous in memory. The memory allocated must
be at least widthheight2 bytes, and must be on an even address.
Data values returned are between 0 and 65535 and are in little-endian
byte order. If you pass an array of 'unsigned short', then you need
not worry about the byte-ordering issues; otherwise the values are
(byte[n]|(byte[n+1]<<8).
data_size_in_bytes -- the number of bytes of 'data'. This is used to
ensure that the library doesn't write past the end of the allocation
of data. This would cause worse problems than a simple segmentation
fault, for reasons given below.
callback -- this is NULL, or the address of a routine to be called
at various points during the readout. It may be called by
sbig_readout() zero or more times, and on each call, returns the
percentage complete (0.0 to 100.0) of the readout operation. If
your callback returns nonzero, then READOUT WILL BE ABORTED. Use this
to cancel a long ST7 or ST8 readout, for example.
You may make NO other sbig calls from your callback routine. It
should do what it needs to do (like updating a progress bar), and
return with due dispatch.
- Important
- Because of nasty timing problems in the SBIG protocol, this call
disables ALL interrupts at various times while it is running. Thus
the system clock will lose time. If some problem occurs while interrupts
are disabled, then your Linux system will do a Windows(TM) imitation and
lockup solid as a rock. It will be time for a reset and a painful fsck.
Until your program is debugged, I recommend calling sync() before every
call to sbig_readout().
Although the code makes a number of paranoia checks, it can't ward off every possible problem. In particular, it locks down all the pages referenced by 'data'. If you get a segmentation fault in sbig_readout(), it will happen here. Fix your memory allocation problem, and be glad it didn't happen while interrupts were off!
- Note
- On my ST-7, the first 3 scanlines of the tracking CCD are garbage.
Therefore, I always set y to 3, and use a height of 159 (3 less than the full
height of 162) when reading the tracking CCD with 1x1 binning.
You can use 'hwclock -hctosys' to reset the system clock from the hardware clock -- see the manpage for clock(8).
h) sbig_set_cooling()
Use this call to set temperature regulation in the camera.
int sbig_set_cooling(struct sbig_cool *cooling_params_input)
where sbig.h defines:
struct sbig_cool {
int regulation;
int temperature;
int direct_drive;
};
The structure element are specified as follows: regulation -- set to 0 to turn off regulation, 1 to turn it on, and 2
to pump current into the cooler without regulation. temperature -- the temperature to use when regulation is set to 1. It
is specified in units of 0.1 deg C (thus -250 sets the target
temperature to -25.0 C).
direct_drive -- the power applied to cooler when regulation is set to
2, in arbitrary units between 0 and 255.
Note, it is advised to turn off regulation, but leave the fan on, for a minute or so prior to shutting down the camera.
- example
- /* regulate at 5.0C */ struct sbig_cool cool; cool.regulation = 1; cool.temperature = 50; ret = sbig_set_cooling(&cool);
i) AO7 support calls
int sbig_set_ao7_deflection(int x_deflection, int y_deflection)
Tips and tilts the AO7 mirror. The deflections are unsigned quantities between 0 and 65535.
j) Linux realtime strategy call
void sbig_set_linux_strategy(int flags)
This call is experimental. Use either flags set to
SBIG_DEFAULT_STRATEGY,
or
(SBIG_DEFAULT_STRATEGY & ~SBIG_LOCK_ALL)
The latter avoids the mlockall system call which may help run in smaller
memory, and possibly download slightly faster. However, if paging
occurs as a result of a readout call, there might be white stripes
in the image.
4 Errors
If a call fails, then it will return a negative error code. These are listed in sbig.h
Use
char *sbig_show_error(int code)
to convert a negative error code into a string. If the value passed is 0, then sbig_show_error returns an empty string. If the value is not an SBIG_XXX code, it returns a nasty message.
5 Release Notes
Processes that link to sbig.a must be very careful with their memory usage. If you get out-of-physical-memory errors, then you are not freeing memory carefully enough or don't have enough physical memory in your PC. If sbig.a is linked to something that does garbage collection, be sure to invoke the collector prior to calling sbig_readout.
If you encounter problems, you might want to make a separate small process that links sbig.a and then transfer the downloaded images using a file, FIFO, socket, or some such technique. Or you could add more memory. I recommend at least 48Mb if you are doing serious image processing with an ST7 or ST8.
