diff options
| author | iximeow <me@iximeow.net> | 2019-03-14 15:51:15 -0700 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2019-03-14 15:51:39 -0700 | 
| commit | 051a2e73d031475e08e37953007fbb7869515fb6 (patch) | |
| tree | 7fa9ecddf5cba16c5f763a5ec1124933b5b9f962 /src | |
add ASI controls
Diffstat (limited to 'src')
| -rw-r--r-- | src/asicam/ASICamera2.rs | 945 | ||||
| -rw-r--r-- | src/asicam/mod.rs | 282 | ||||
| -rw-r--r-- | src/main.rs | 76 | 
3 files changed, 1303 insertions, 0 deletions
| diff --git a/src/asicam/ASICamera2.rs b/src/asicam/ASICamera2.rs new file mode 100644 index 0000000..7d029db --- /dev/null +++ b/src/asicam/ASICamera2.rs @@ -0,0 +1,945 @@ +/* automatically generated by rust-bindgen */ +use std::os; + +pub struct CameraHandle(i32); + +pub const CAMERA_ID_MAX: u32 = 128; +#[repr(u32)] +#[derive(Copy, Clone, Debug)] +pub enum BayerPattern { +    RG = 0, +    BG = 1, +    GR = 2, +    GB = 3 +} + +#[repr(u32)] +#[derive(Copy, Clone, Debug)] +pub enum ImageType { +    RAW8 = 0, +    RGB24 = 1, +    RAW16 = 2, +    Y8 = 3, +    END = 0xffffffff +} +/* +pub const ASI_GUIDE_DIRECTION_ASI_GUIDE_NORTH: ASI_GUIDE_DIRECTION = 0; +pub const ASI_GUIDE_DIRECTION_ASI_GUIDE_SOUTH: ASI_GUIDE_DIRECTION = 1; +pub const ASI_GUIDE_DIRECTION_ASI_GUIDE_EAST: ASI_GUIDE_DIRECTION = 2; +pub const ASI_GUIDE_DIRECTION_ASI_GUIDE_WEST: ASI_GUIDE_DIRECTION = 3; +pub type ASI_GUIDE_DIRECTION = u32; +*/ +#[repr(u32)] +#[derive(Copy, Clone, Debug)] +pub enum FlipStatus { +    None = 0, +    Horizontal = 1, +    Vertical = 2, +    Both = 3 +} + +#[repr(u32)] +#[derive(Copy, Clone, Debug)] +pub enum ErrorCode { +    Success = 0, +    InvalidIndex = 1, +    InvalidId = 2, +    InvalidControlType = 3, +    CameraClosed = 4, +    CameraRemoved = 5, +    InvalidPath = 6, +    InvalidFileformat = 7, +    InvalidSize = 8, +    InvalidImgtype = 9, +    OutofBoundary = 10, +    Timeout = 11, +    InvalidSequence = 12, +    BufferTooSmall = 13, +    VideoModeActive = 14, +    ExposureInProgress = 15, +    GeneralError = 16, +    InvalidMode = 17, +    End = 18 +} + +#[repr(u32)] +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum AsiBool { +    False = 0, +    True = 1 +} + +impl From<AsiBool> for bool { +    fn from(asi_bool: AsiBool) -> Self { +        match asi_bool { +            AsiBool::False => false, +            AsiBool::True => true +        } +    } +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CameraInfo { +    pub name: [os::raw::c_char; 64usize], +    pub camera_id: os::raw::c_int, +    pub max_height: os::raw::c_long, +    pub max_width: os::raw::c_long, +    pub is_color_cam: AsiBool, +    pub bayer_pattern: BayerPattern, +    pub supported_bins: [os::raw::c_int; 16usize ], +    pub supported_video_format: [ImageType; 8usize ], +    pub pixel_size: f64, +    pub mechanical_shutter: AsiBool, +    pub ST4_port: AsiBool, +    pub is_cooler_cam: AsiBool, +    pub is_USB3_host: AsiBool, +    pub is_USB3_camera: AsiBool, +    pub elec_per_ADU: f32, +    pub bit_depth: os::raw::c_int, +    pub is_trigger_cam: AsiBool, +    pub unused: [os::raw::c_char; 16usize ] +} + +#[repr(u32)] +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] +pub enum ControlType { +    Gain = 0, +    Exposure = 1, +    Gamma = 2, +    WB_R = 3, +    WB_B = 4, +    Offset = 5, +    BandwidthOverload = 6, +    Overclock = 7, +    Temperature = 8, +    Flip = 9, +    AutoMaxGain = 10, +    AutoMaxExp = 11, +    AutoTargetBrightness = 12, +    HardwareBin = 13, +    HighSpeedMode = 14, +    CoolerPowerPerc = 15, +    TargetTemp = 16, +    CoolerOn = 17, +    MonoBin = 18, +    FanOn = 19, +    PatternAdjust = 20, +    AntiDewHeater = 21 +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct ControlCaps { +    pub name: [os::raw::c_char; 64usize ], +    pub description: [os::raw::c_char; 128usize ], +    pub max_value: os::raw::c_long, +    pub min_value: os::raw::c_long, +    pub default_value: os::raw::c_long, +    pub is_auto_supported: AsiBool, +    pub is_writable: AsiBool, +    pub control_type: ControlType, +    pub Unused: [os::raw::c_char; 32usize ] +} + +#[repr(u32)] +#[derive(Copy, Clone, Debug)] +pub enum ExposureStatus { +    Idle = 0, +    Working = 1, +    Success = 2, +    Failed = 3 +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct ID { +    pub id: [os::raw::c_uchar; 8usize ] +} + +extern "C" { +    #[doc = "this should be the first API to be called"] +    #[doc = "get number of connected ASI cameras"] +    pub fn ASIGetNumOfConnectedCameras() -> os::raw::c_int; +} +extern "C" { +#[doc = "get the product ID of each supported camera, at first set pPIDs as 0 and get length and then malloc a buffer to contain the PIDs"] +#[doc = "Return: length of the array."] +    pub fn ASIGetProductIDs(pPIDs: *mut os::raw::c_int) -> ErrorCode; +} +extern "C" { +# [ doc = "get the property of the connected cameras, you can do this without open the camera." ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "ASI_CAMERA_INFO *pASICameraInfo: Pointer to structure containing the property of camera" ] +# [ doc = "user need to malloc the buffer" ] +# [ doc = "int iCameraIndex: 0 means the first connect camera, 1 means the second connect camera" ] +# [ doc = "" ] +# [ doc = "return\u{fffd}\u{fffd}" ] +# [ doc = "ASI_SUCCESS: Operation is successful" ] +# [ doc = "ASI_ERROR_INVALID_INDEX  :no camera connected or index value out of boundary" ] +    pub fn ASIGetCameraProperty(pASICameraInfo: *mut CameraInfo, iCameraIndex: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "open the camera before any operation to the camera, this will not affect the camera which is capturing" ] +# [ doc = "All APIs below need to open the camera at first." ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "" ] +# [ doc = "return\u{fffd}\u{fffd}" ] +# [ doc = "ASI_SUCCESS: Operation is successful" ] +# [ doc = "ASI_ERROR_INVALID_ID  : no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_CAMERA_REMOVED: failed to find the camera, maybe camera has been removed" ] +    pub fn ASIOpenCamera(iCameraID : os::raw::c_int) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions" ] +# [ doc = "" ] +# [ doc = "Initialise the camera after open, this function may take some while, this will affect the camera which is capturing" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIInitCamera (iCameraID: os::raw::c_int) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "you need to close the camera to free all the resource" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "" ] +# [ doc = "return\u{fffd}\u{fffd}" ] +# [ doc = "ASI_SUCCESS :it will return success even the camera already closed" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASICloseCamera (iCameraID : os::raw::c_int) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Get number of controls available for this camera. the camera need be opened at first." ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int * piNumberOfControls: pointer to an int to save the number of controls" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetNumOfControls ( iCameraID: os::raw::c_int , piNumberOfControls : * mut os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Get controls property available for this camera. the camera need be opened at first." ] +# [ doc = "user need to malloc and maintain the buffer." ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int iControlIndex: index of control, NOT control type" ] +# [ doc = "ControlCaps * pControlCaps: Pointer to structure containing the property of the control" ] +# [ doc = "user need to malloc the buffer" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetControlCaps ( iCameraID: os::raw::c_int , iControlIndex: os::raw::c_int , pControlCaps : * mut ControlCaps ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Get controls property value and auto value" ] +# [ doc = "note:the value of the temperature is the float value * 10 to convert it to long type, control name is \"Temperature\"" ] +# [ doc = "because long is the only type for control(except cooler\'s target temperature, because it is an integer)" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int ControlType: this is get from control property use the API ASIGetControlCaps" ] +# [ doc = "long *plValue: pointer to the value you want to save the value get from control" ] +# [ doc = "AsiBool *pbAuto: pointer to the AsiBool type" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_INVALID_CONTROL_TYPE, //invalid Control type" ] +    pub fn ASIGetControlValue ( iCameraID: os::raw::c_int , ControlType: os::raw::c_int , plValue : * mut os::raw::c_long , pbAuto : * mut os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Set controls property value and auto value" ] +# [ doc = "it will return success and set the max value or min value if the value is beyond the boundary" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int ControlType: this is get from control property use the API ASIGetControlCaps" ] +# [ doc = "long lValue: the value set to the control" ] +# [ doc = "AsiBool bAuto: set the control auto" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_INVALID_CONTROL_TYPE, //invalid Control type" ] +# [ doc = "ASI_ERROR_GENERAL_ERROR,//general error, eg: value is out of valid range; operate to camera hareware failed" ] +    pub fn ASISetControlValue ( iCameraID: os::raw::c_int , ControlType: os::raw::c_int , lValue: os::raw::c_long , bAuto: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "set the ROI area before capture." ] +# [ doc = "you must stop capture before call it." ] +# [ doc = "the width and height is the value after binning." ] +# [ doc = "ie. you need to set width to 640 and height to 480 if you want to run at 640X480@BIN2" ] +# [ doc = "ASI120\'s data size must be times of 1024 which means width*height%1024=0" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int iWidth,  the width of the ROI area. Make sure iWidth%8 = 0." ] +# [ doc = "int iHeight,  the height of the ROI area. Make sure iHeight%2 = 0," ] +# [ doc = "further, for USB2.0 camera ASI120, please make sure that iWidth*iHeight%1024=0." ] +# [ doc = "int iBin,   binning method. bin1=1, bin2=2" ] +# [ doc = "ASI_IMG_TYPE Img_type: the output format you want" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_INVALID_SIZE, //wrong video format size" ] +# [ doc = "ASI_ERROR_INVALID_IMGTYPE, //unsupported image format, make sure iWidth and iHeight and binning is set correct" ] +    pub fn ASISetROIFormat ( iCameraID: os::raw::c_int , iWidth: os::raw::c_int , iHeight: os::raw::c_int , iBin: os::raw::c_int , Img_type: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Start camera exposure. the following 4 API is usually used when long exposure required" ] +# [ doc = "start exposure  and check the exposure status then get the data" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "AsiBool bIsDark: means dark frame if there is mechanical shutter on the camera. otherwise useless" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_VIDEO_MODE_ACTIVE: video mode is working, you need to stop video capture first" ] +    pub fn ASIStartExposure ( iCameraID: os::raw::c_int , bIsDark: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "to cancel the long exposure which is on." ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIStopExposure ( iCameraID: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "to get the exposure status, work with ASIStartExposure." ] +# [ doc = "you can read the data if get ASI_EXP_SUCCESS. or have to restart exposure again" ] +# [ doc = "if get ASI_EXP_FAILED" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "ASI_EXPOSURE_STATUS *pExpStatus: the exposure status" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetExpStatus ( iCameraID: os::raw::c_int , pExpStatus : * mut ExposureStatus ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "get data after exposure." ] +# [ doc = "please make sure the buffer size is biger enough to hold one image" ] +# [ doc = "otherwise the this API will crash" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "unsigned char* pBuffer, caller need to malloc the buffer, make sure the size is big enough" ] +# [ doc = "the size in byte:" ] +# [ doc = "8bit mono:width*height" ] +# [ doc = "16bit mono:width*height*2" ] +# [ doc = "RGB24:width*height*3" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_TIMEOUT: no image get and timeout" ] +    pub fn ASIGetDataAfterExp ( iCameraID: os::raw::c_int , pBuffer : * mut os::raw::c_uchar , lBuffSize: os::raw::c_long ) -> ErrorCode; +} +/* +# [ repr ( C ) ] +# [ derive ( Debug , Copy , Clone ) ] +    pub struct _ASI_SUPPORTED_MODE { pub SupportedCameraMode : [ ASI_CAMERA_MODE; +16usize ] , } +} pub type ASI_SUPPORTED_MODE = _ASI_SUPPORTED_MODE; +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "this should be the first API to be called" ] +# [ doc = "get number of connected ASI cameras," ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "" ] +# [ doc = "return\u{fffd}\u{fffd}number of connected ASI cameras. 1 means 1 camera connected." ] +    pub fn ASIGetNumOfConnectedCameras ( ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions:" ] +# [ doc = "get the product ID of each supported camera, at first set pPIDs as 0 and get length and then malloc a buffer to contain the PIDs" ] +# [ doc = "" ] +# [ doc = "Paras:" ] +# [ doc = "int* pPIDs: pointer to array of PIDs" ] +# [ doc = "" ] +# [ doc = "Return: length of the array." ] +    pub fn ASIGetProductIDs ( pPIDs : * mut os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "get the property of the connected cameras, you can do this without open the camera." ] +# [ doc = "here is the sample code:" ] +# [ doc = "" ] +# [ doc = "int iNumofConnectCameras = ASIGetNumOfConnectedCameras();" ] +# [ doc = "ASI_CAMERA_INFO **ppASICameraInfo = (ASI_CAMERA_INFO **)malloc(sizeof(ASI_CAMERA_INFO *)*iNumofConnectCameras);" ] +# [ doc = "for(int i = 0; i < iNumofConnectCameras; i++)" ] +# [ doc = "{" ] +# [ doc = "ppASICameraInfo[i] = (ASI_CAMERA_INFO *)malloc(sizeof(ASI_CAMERA_INFO ));" ] +# [ doc = "ASIGetCameraProperty(ppASICameraInfo[i], i);" ] +# [ doc = "}" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "ASI_CAMERA_INFO *pASICameraInfo: Pointer to structure containing the property of camera" ] +# [ doc = "user need to malloc the buffer" ] +# [ doc = "int iCameraIndex: 0 means the first connect camera, 1 means the second connect camera" ] +# [ doc = "" ] +# [ doc = "return\u{fffd}\u{fffd}" ] +# [ doc = "ASI_SUCCESS: Operation is successful" ] +# [ doc = "ASI_ERROR_INVALID_INDEX  :no camera connected or index value out of boundary" ] +    pub fn ASIGetCameraProperty ( pASICameraInfo : * mut ASI_CAMERA_INFO , iCameraIndex: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "open the camera before any operation to the camera, this will not affect the camera which is capturing" ] +# [ doc = "All APIs below need to open the camera at first." ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "" ] +# [ doc = "return\u{fffd}\u{fffd}" ] +# [ doc = "ASI_SUCCESS: Operation is successful" ] +# [ doc = "ASI_ERROR_INVALID_ID  : no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_CAMERA_REMOVED: failed to find the camera, maybe camera has been removed" ] +    pub fn ASIOpenCamera ( iCameraID: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions" ] +# [ doc = "" ] +# [ doc = "Initialise the camera after open, this function may take some while, this will affect the camera which is capturing" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIInitCamera ( iCameraID: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "you need to close the camera to free all the resource" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "" ] +# [ doc = "return\u{fffd}\u{fffd}" ] +# [ doc = "ASI_SUCCESS :it will return success even the camera already closed" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASICloseCamera ( iCameraID: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Get number of controls available for this camera. the camera need be opened at first." ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int * piNumberOfControls: pointer to an int to save the number of controls" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetNumOfControls ( iCameraID: os::raw::c_int , piNumberOfControls : * mut os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Get controls property available for this camera. the camera need be opened at first." ] +# [ doc = "user need to malloc and maintain the buffer." ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int iControlIndex: index of control, NOT control type" ] +# [ doc = "ControlCaps * pControlCaps: Pointer to structure containing the property of the control" ] +# [ doc = "user need to malloc the buffer" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetControlCaps ( iCameraID: os::raw::c_int , iControlIndex: os::raw::c_int , pControlCaps : * mut ControlCaps ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Get controls property value and auto value" ] +# [ doc = "note:the value of the temperature is the float value * 10 to convert it to long type, control name is \"Temperature\"" ] +# [ doc = "because long is the only type for control(except cooler\'s target temperature, because it is an integer)" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int ControlType: this is get from control property use the API ASIGetControlCaps" ] +# [ doc = "long *plValue: pointer to the value you want to save the value get from control" ] +# [ doc = "AsiBool *pbAuto: pointer to the AsiBool type" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_INVALID_CONTROL_TYPE, //invalid Control type" ] +    pub fn ASIGetControlValue ( iCameraID: os::raw::c_int , ControlType: os::raw::c_int , plValue : * mut os::raw::c_long , pbAuto : * mut os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Set controls property value and auto value" ] +# [ doc = "it will return success and set the max value or min value if the value is beyond the boundary" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int ControlType: this is get from control property use the API ASIGetControlCaps" ] +# [ doc = "long lValue: the value set to the control" ] +# [ doc = "AsiBool bAuto: set the control auto" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_INVALID_CONTROL_TYPE, //invalid Control type" ] +# [ doc = "ASI_ERROR_GENERAL_ERROR,//general error, eg: value is out of valid range; operate to camera hareware failed" ] +    pub fn ASISetControlValue ( iCameraID: os::raw::c_int , ControlType: os::raw::c_int , lValue: os::raw::c_long , bAuto: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "set the ROI area before capture." ] +# [ doc = "you must stop capture before call it." ] +# [ doc = "the width and height is the value after binning." ] +# [ doc = "ie. you need to set width to 640 and height to 480 if you want to run at 640X480@BIN2" ] +# [ doc = "ASI120\'s data size must be times of 1024 which means width*height%1024=0" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int iWidth,  the width of the ROI area. Make sure iWidth%8 = 0." ] +# [ doc = "int iHeight,  the height of the ROI area. Make sure iHeight%2 = 0," ] +# [ doc = "further, for USB2.0 camera ASI120, please make sure that iWidth*iHeight%1024=0." ] +# [ doc = "int iBin,   binning method. bin1=1, bin2=2" ] +# [ doc = "ASI_IMG_TYPE Img_type: the output format you want" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_INVALID_SIZE, //wrong video format size" ] +# [ doc = "ASI_ERROR_INVALID_IMGTYPE, //unsupported image format, make sure iWidth and iHeight and binning is set correct" ] +    pub fn ASISetROIFormat ( iCameraID: os::raw::c_int , iWidth: os::raw::c_int , iHeight: os::raw::c_int , iBin: os::raw::c_int , Img_type: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Get the current ROI area setting ." ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int *piWidth,  pointer to the width of the ROI area" ] +# [ doc = "int *piHeight, pointer to the height of the ROI area." ] +# [ doc = "int *piBin,   pointer to binning method. bin1=1, bin2=2" ] +# [ doc = "ASI_IMG_TYPE *pImg_type: pointer to the output format" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetROIFormat ( iCameraID: os::raw::c_int , piWidth : * mut os::raw::c_int , piHeight : * mut os::raw::c_int , piBin : * mut os::raw::c_int , pImg_type : * mut os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Set the start position of the ROI area." ] +# [ doc = "you can call this API to move the ROI area when video is streaming" ] +# [ doc = "the camera will set the ROI area to the center of the full image as default" ] +# [ doc = "at bin2 or bin3 mode, the position is relative to the image after binning" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int iStartX, pointer to the start X" ] +# [ doc = "int iStartY  pointer to the start Y" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_OUTOF_BOUNDARY: the start x and start y make the image out of boundary" ] +    pub fn ASISetStartPos ( iCameraID: os::raw::c_int , iStartX: os::raw::c_int , iStartY: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Get the start position of current ROI area ." ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int *piStartX, pointer to the start X" ] +# [ doc = "int *piStartY  pointer to the start Y" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetStartPos ( iCameraID: os::raw::c_int , piStartX : * mut os::raw::c_int , piStartY : * mut os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Get the droped frames ." ] +# [ doc = "drop frames happen when USB is traffic or harddisk write speed is slow" ] +# [ doc = "it will reset to 0 after stop capture" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "int *piDropFrames pointer to drop frames" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetDroppedFrames ( iCameraID: os::raw::c_int , piDropFrames : * mut os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "provide a dark file\'s path to the function and enable dark subtract" ] +# [ doc = "this is used when there is hot pixel or need to do long exposure" ] +# [ doc = "you\'d better make this dark file from the  \"dark subtract\" funtion" ] +# [ doc = "of the \"video capture filter\" directshow page." ] +# [ doc = "the dark file\'s size should be the same of camera\'s max width and height" ] +# [ doc = "and should be RGB8 raw format.it will on even you changed the ROI setting" ] +# [ doc = "it only correct the hot pixels if out put isn\'t 16bit." ] +# [ doc = "" ] +# [ doc = "it will be remembered in registry. so \"Dark subtract\" is on next time if you close your app." ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "char *pcBMPPath: the path to the bmp dark file." ] +# [ doc = "return\u{fffd}\u{fffd}" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_PATH, //cannot find the path of the file" ] +# [ doc = "ASI_ERROR_INVALID_FILEFORMAT, //the dark file\'s size should be the same of camera\'s max width and height" ] +    pub fn ASIEnableDarkSubtract ( iCameraID: os::raw::c_int , pcBMPPath : * mut os::raw::c_char ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Disable the dark subtract function." ] +# [ doc = "you\'d better call it at start if you don\'t want to use it." ] +# [ doc = "because dark subtract function is remembered on windows platform" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +    pub fn ASIDisableDarkSubtract ( iCameraID: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Start video capture" ] +# [ doc = "then you can get the data from the API ASIGetVideoData" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful, it will return success if already started" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_EXPOSURE_IN_PROGRESS: snap mode is working, you need to stop snap first" ] +    pub fn ASIStartVideoCapture ( iCameraID: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Stop video capture" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful, it will return success if already stopped" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIStopVideoCapture ( iCameraID: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "get data from the video buffer.the buffer is very small" ] +# [ doc = "you need to call this API as fast as possible, otherwise frame will be discarded" ] +# [ doc = "so the best way is maintain one buffer loop and call this API in a loop" ] +# [ doc = "please make sure the buffer size is biger enough to hold one image" ] +# [ doc = "otherwise the this API will crash" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "unsigned char* pBuffer, caller need to malloc the buffer, make sure the size is big enough" ] +# [ doc = "the size in byte:" ] +# [ doc = "8bit mono:width*height" ] +# [ doc = "16bit mono:width*height*2" ] +# [ doc = "RGB24:width*height*3" ] +# [ doc = "" ] +# [ doc = "int iWaitms, this API will block and wait iWaitms to get one image. the unit is ms" ] +# [ doc = "-1 means wait forever. this value is recommend set to exposure*2+500ms" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_TIMEOUT: no image get and timeout" ] +    pub fn ASIGetVideoData ( iCameraID: os::raw::c_int , pBuffer : * mut os::raw::c_uchar , lBuffSize: os::raw::c_long , iWaitms: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "PulseGuide of the ST4 port on. this function only work on the module which have ST4 port" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "ASI_GUIDE_DIRECTION direction the direction of guider" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIPulseGuideOn ( iCameraID: os::raw::c_int , direction: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "PulseGuide of the ST4 port off. this function only work on the module which have ST4 port" ] +# [ doc = "make sure where is ASIPulseGuideOn and there is ASIPulseGuideOff" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "ASI_GUIDE_DIRECTION direction the direction of guider" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIPulseGuideOff ( iCameraID: os::raw::c_int , direction: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "Start camera exposure. the following 4 API is usually used when long exposure required" ] +# [ doc = "start exposure  and check the exposure status then get the data" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "AsiBool bIsDark: means dark frame if there is mechanical shutter on the camera. otherwise useless" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_VIDEO_MODE_ACTIVE: video mode is working, you need to stop video capture first" ] +    pub fn ASIStartExposure ( iCameraID: os::raw::c_int , bIsDark: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "to cancel the long exposure which is on." ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIStopExposure ( iCameraID: os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "to get the exposure status, work with ASIStartExposure." ] +# [ doc = "you can read the data if get ASI_EXP_SUCCESS. or have to restart exposure again" ] +# [ doc = "if get ASI_EXP_FAILED" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "ASI_EXPOSURE_STATUS *pExpStatus: the exposure status" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetExpStatus ( iCameraID: os::raw::c_int , pExpStatus : * mut ASI_EXPOSURE_STATUS ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "get data after exposure." ] +# [ doc = "please make sure the buffer size is biger enough to hold one image" ] +# [ doc = "otherwise the this API will crash" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "unsigned char* pBuffer, caller need to malloc the buffer, make sure the size is big enough" ] +# [ doc = "the size in byte:" ] +# [ doc = "8bit mono:width*height" ] +# [ doc = "16bit mono:width*height*2" ] +# [ doc = "RGB24:width*height*3" ] +# [ doc = "" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +# [ doc = "ASI_ERROR_TIMEOUT: no image get and timeout" ] +    pub fn ASIGetDataAfterExp ( iCameraID: os::raw::c_int , pBuffer : * mut os::raw::c_uchar , lBuffSize: os::raw::c_long ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "get camera id stored in flash, only available for USB3.0 camera" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "ASI_ID* pID: pointer to ID" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetID ( iCameraID: os::raw::c_int , pID : * mut ASI_ID ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "write camera id to flash, only available for USB3.0 camera" ] +# [ doc = "" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "ASI_ID ID: ID" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASISetID ( iCameraID: os::raw::c_int , ID : ASI_ID ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "get pre-setting parameter" ] +# [ doc = "Paras\u{fffd}\u{fffd}" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "Offset_HighestDR: offset at highest dynamic range," ] +# [ doc = "Offset_UnityGain: offset at unity gain" ] +# [ doc = "int *Gain_LowestRN, *Offset_LowestRN: gain and offset at lowest read noise" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetGainOffset ( iCameraID: os::raw::c_int , pOffset_HighestDR : * mut os::raw::c_int , pOffset_UnityGain : * mut os::raw::c_int , pGain_LowestRN : * mut os::raw::c_int , pOffset_LowestRN : * mut os::raw::c_int ) -> ErrorCode; +} +extern "C" { +# [ doc = "Descriptions\u{fffd}\u{fffd}" ] +# [ doc = "get version string, like \"1, 13, 0503\"" ] +    pub fn ASIGetSDKVersion ( ) -> * mut os::raw::c_char; +} +extern "C" { +# [ doc = "Description:" ] +# [ doc = "Get the camera supported mode, only need to call when the IsTriggerCam in the CameraInfo is true." ] +# [ doc = "Paras:" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "ASI_SUPPORTED_MODE: the camera supported mode" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetCameraSupportMode ( iCameraID: os::raw::c_int , pSupportedMode : * mut ASI_SUPPORTED_MODE ) -> ErrorCode; +} +extern "C" { +# [ doc = "Description:" ] +# [ doc = "Get the camera current mode, only need to call when the IsTriggerCam in the CameraInfo is true" ] +# [ doc = "Paras:" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "ASI_CAMERA_MODE: the current camera mode" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_ID  :no camera of this ID is connected or ID value is out of boundary" ] +    pub fn ASIGetCameraMode ( iCameraID: os::raw::c_int , mode : * mut ASI_CAMERA_MODE ) -> ErrorCode; +} +extern "C" { +# [ doc = "Description:" ] +# [ doc = "Set the camera mode, only need to call when the IsTriggerCam in the CameraInfo is true" ] +# [ doc = "Paras:" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "ASI_CAMERA_MODE: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "" ] +# [ doc = "return:" ] +# [ doc = "ASI_SUCCESS : Operation is successful" ] +# [ doc = "ASI_ERROR_CAMERA_CLOSED : camera didn\'t open" ] +# [ doc = "ASI_ERROR_INVALID_SEQUENCE : camera is in capture now, need to stop capture first." ] +# [ doc = "ASI_ERROR_INVALID_MODE  : mode is out of boundary or this camera do not support this mode" ] +    pub fn ASISetCameraMode ( iCameraID: os::raw::c_int , mode : ASI_CAMERA_MODE ) -> ErrorCode; +} +extern "C" { +# [ doc = "Description:" ] +# [ doc = "Send out a softTrigger. For edge trigger, it only need to set true which means send a" ] +# [ doc = "rising trigger to start exposure. For level trigger, it need to set true first means" ] +# [ doc = "start exposure, and set false means stop exposure.it only need to call when the" ] +# [ doc = "IsTriggerCam in the CameraInfo is true" ] +# [ doc = "Paras:" ] +# [ doc = "int CameraID: this is get from the camera property use the API ASIGetCameraProperty" ] +# [ doc = "AsiBool starts:send a softTrigger start/stop signal" ] +    pub fn ASISendSoftTrigger ( iCameraID: os::raw::c_int , bStart: os::raw::c_int ) -> ErrorCode; +} +*/ diff --git a/src/asicam/mod.rs b/src/asicam/mod.rs new file mode 100644 index 0000000..01b9ce7 --- /dev/null +++ b/src/asicam/mod.rs @@ -0,0 +1,282 @@ +pub mod ASICamera2; + +use self::ASICamera2::{CameraInfo, ControlCaps, ControlType, ExposureStatus, ImageType}; + +use std::alloc::{alloc, dealloc, Layout}; +use std::collections::HashMap; +use std::ffi::CStr; +use std::os; +use std::fs::File; +use std::io::BufWriter; +use std::path::Path; + +use png::HasParameters; + +#[derive(Debug)] +pub struct Control { +    pub name: String, +    pub description: String, +    pub max: i64, +    pub min: i64, +    pub default: i64, +    pub can_auto: bool, +    pub is_writable: bool, +    pub control_type: ASICamera2::ControlType +} + +#[derive(Debug)] +pub struct Camera { +    id: i32, +    pub width: u32, +    pub height: u32, +    curr_width: u32, +    curr_height: u32, +    bin: u8, +    color_format: ASICamera2::ImageType, +    image_buffer: *mut u8, +    controls: HashMap<ASICamera2::ControlType, Control> +} + +impl Camera { +    pub fn new(id: i32) -> Camera { +        Camera { +            id: id, +            controls: HashMap::new(), +            width: 0, +            height: 0, +            curr_width: 0, +            curr_height: 0, +            bin: 1, +            image_buffer: std::ptr::null_mut(), +            color_format: ASICamera2::ImageType::END +        } +    } + +    pub fn get_control_value(&self, control: ASICamera2::ControlType) -> Result<i64> { +        let mut current: os::raw::c_long = 0; +        let mut is_auto: os::raw::c_int = 0; +        let res = +            unsafe { +                ASICamera2::ASIGetControlValue( +                    self.id, +                    control as i32, +                    &mut current as *mut os::raw::c_long, +                    &mut is_auto as *mut os::raw::c_int +                ) +            }; +        build_result(current, res) +    } + +    pub fn set_control_value(&mut self, control: ASICamera2::ControlType, value: i64) -> Result<()> { +        let res = +            unsafe { +                ASICamera2::ASISetControlValue( +                    self.id, +                    control as i32, +                    value, +                    0 +                ) +            }; +        build_result((), res)?; +        match control { +            ControlType::HardwareBin => { +                if value == 0 { +                    self.curr_width *= 2; +                    self.curr_height *= 2; +                    Ok(()) +                } else if value == 1 { +                    self.curr_width /= 2; +                    self.curr_height /= 2; +                    Ok(()) +                } else { +                    // pretty sure this is unreachable, +                    // would be an out of band value and fail in `build_result` +                    unreachable!(); +                } +            } +            _ => Ok(()) +        } +    } + +    pub fn set_exposure_ms(&mut self, ms: u64) -> Result<()> { +        self.set_control_value(ControlType::Exposure, ms as i64 * 1000) +    } + +    pub fn take_image(&self, path: &str) -> Result<()> { +        let exposure_duration = self.get_control_value(ControlType::Exposure).unwrap(); +        let exposure_ms = exposure_duration / 1000; +        unsafe { +            let res = ASICamera2::ASIStartExposure(self.id, 0); // isDark == false, doesnt matter really +            build_result((), res)?; +        } + +        println!("Sleeping {}ms", exposure_ms + 2500); +        std::thread::sleep(std::time::Duration::from_millis(exposure_ms as u64 + 2500)); + +        let res = unsafe { +            ASICamera2::ASIGetDataAfterExp( +                self.id, +                self.image_buffer, +                self.curr_width as i64 * self.curr_height as i64 * 3 +            ) +        }; +        build_result((), res)?; + +        let dest = Path::new(path); +        let file = File::create(dest).unwrap(); +        let ref mut w = BufWriter::new(file); +        let mut encoder = png::Encoder::new(w, self.curr_width, self.curr_height); +        encoder.set(png::ColorType::RGB).set(png::BitDepth::Eight); +        let mut writer = encoder.write_header().unwrap(); +        writer.write_image_data( +            unsafe { +                std::slice::from_raw_parts( +                    self.image_buffer, +                    self.curr_width as usize * self.curr_height as usize* 3 +                ) +            } +        ).unwrap(); +        Ok(()) +    } + +    pub fn exposure_status(&self) -> Result<ExposureStatus> { +        let mut exposure_status = ExposureStatus::Failed; +        let res = unsafe { +            ASICamera2::ASIGetExpStatus(self.id, &mut exposure_status as *mut ExposureStatus) +        }; +        build_result(exposure_status, res) +    } + +    pub fn set_roi_format(&mut self, width: u32, height: u32, binning: u8, image_type: ImageType) -> Result<()> { +        self.curr_width = width - (width % 8); +        self.curr_height = height - (height % 8); +        self.bin = binning; +        let res = unsafe { +            ASICamera2::ASISetROIFormat( +                self.id, +                self.curr_width as i32, +                self.curr_height as i32, +                self.bin as i32, +                image_type as i32) +        }; +        build_result((), res) +    } +} + +#[derive(Copy, Clone, Debug)] +pub enum CameraError { +    InvalidIndex = 1, +    InvalidId = 2, +    InvalidControlType = 3, +    CameraClosed = 4, +    CameraRemoved = 5, +    InvalidPath = 6, +    InvalidFileformat = 7, +    InvalidSize = 8, +    InvalidImgtype = 9, +    OutofBoundary = 10, +    Timeout = 11, +    InvalidSequence = 12, +    BufferTooSmall = 13, +    VideoModeActive = 14, +    ExposureInProgress = 15, +    GeneralError = 16, +    InvalidMode = 17, +    End = 18 +} + +fn build_result<T>(value: T, err: ASICamera2::ErrorCode) -> Result<T> { +    match err { +        ASICamera2::ErrorCode::Success => { Ok(value) } +        ASICamera2::ErrorCode::InvalidIndex => { Err(CameraError::InvalidIndex) } +        ASICamera2::ErrorCode::InvalidId => { Err(CameraError::InvalidId) } +        ASICamera2::ErrorCode::InvalidControlType => { Err(CameraError::InvalidControlType) } +        ASICamera2::ErrorCode::CameraClosed => { Err(CameraError::CameraClosed) } +        ASICamera2::ErrorCode::CameraRemoved => { Err(CameraError::CameraRemoved) } +        ASICamera2::ErrorCode::InvalidPath => { Err(CameraError::InvalidPath) } +        ASICamera2::ErrorCode::InvalidFileformat => { Err(CameraError::InvalidFileformat) } +        ASICamera2::ErrorCode::InvalidSize => { Err(CameraError::InvalidSize) } +        ASICamera2::ErrorCode::InvalidImgtype => { Err(CameraError::InvalidImgtype) } +        ASICamera2::ErrorCode::OutofBoundary => { Err(CameraError::OutofBoundary) } +        ASICamera2::ErrorCode::Timeout => { Err(CameraError::Timeout) } +        ASICamera2::ErrorCode::InvalidSequence => { Err(CameraError::InvalidSequence) } +        ASICamera2::ErrorCode::BufferTooSmall => { Err(CameraError::BufferTooSmall) } +        ASICamera2::ErrorCode::VideoModeActive => { Err(CameraError::VideoModeActive) } +        ASICamera2::ErrorCode::ExposureInProgress => { Err(CameraError::ExposureInProgress) } +        ASICamera2::ErrorCode::GeneralError => { Err(CameraError::GeneralError) } +        ASICamera2::ErrorCode::InvalidMode => { Err(CameraError::InvalidMode) } +        ASICamera2::ErrorCode::End => { Err(CameraError::End) } +    } +} + +type Result<T> = std::result::Result<T, CameraError>; + +pub fn acquire(camera_id: i32) -> Result<Camera> { +    unsafe { +        let cameracount = ASICamera2::ASIGetNumOfConnectedCameras(); +        if camera_id >= cameracount { +            panic!("Camera id is invalid (detected {} cameras)", camera_id); +        } +        let props_layout = Layout::array::<CameraInfo>(cameracount as usize).unwrap(); +        let props = alloc(props_layout) as *mut CameraInfo; +        let res = ASICamera2::ASIGetCameraProperty(props, camera_id); +        build_result((), res)?; +        println!("Got properties"); + +        let res = ASICamera2::ASIOpenCamera(camera_id); +        build_result((), res)?; +        println!("Opened camera"); + +        let res = ASICamera2::ASIInitCamera(camera_id); +        build_result((), res)?; +        println!("Init'd camera"); + +        let mut control_count: i32 = 0; +        let res = ASICamera2::ASIGetNumOfControls(camera_id, &mut control_count as *mut os::raw::c_int); +        build_result((), res)?; +        println!("Got control count"); + +        let control_layout = Layout::array::<ControlCaps>(1).unwrap(); +        let control = alloc(control_layout) as *mut ControlCaps; + +        let mut camera = Camera::new(camera_id); + +        let camera_props: CameraInfo = *props.offset(camera_id as isize); +        camera.width = camera_props.max_width as u32; +        camera.height = camera_props.max_height as u32; +        camera.curr_width = camera_props.max_width as u32; +        camera.curr_height = camera_props.max_height as u32; +        camera.color_format = ImageType::RGB24; +        camera.image_buffer = alloc( +            Layout::from_size_align(camera.curr_width as usize * camera.curr_height as usize * 3, 8).unwrap() +        ); + +        let res = ASICamera2::ASISetROIFormat(camera_id, camera.width as i32, camera.height as i32, 1, ImageType::RGB24 as i32); +        build_result((), res)?; +        println!("Set ROI/Format"); + +        for c in 0..control_count { +            let res = ASICamera2::ASIGetControlCaps(0, c, control); +            build_result((),  res)?; +            println!("Got control {:?}", c); + +            let control = Control { +                name: CStr::from_ptr((*control).name.as_ptr()).to_str().unwrap().to_owned(), +                description: CStr::from_ptr((*control).description.as_ptr()).to_str().unwrap().to_owned(), +                max: (*control).max_value, +                min: (*control).min_value, +                default: (*control).default_value, +                can_auto: bool::from((*control).is_auto_supported), +                is_writable: bool::from((*control).is_writable), +                control_type: (*control).control_type +            }; + +            camera.controls.insert(control.control_type, control); +        } + +        dealloc(control as *mut u8, control_layout); +        dealloc(props as *mut u8, props_layout); + +        Ok(camera) +    } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..a9a664b --- /dev/null +++ b/src/main.rs @@ -0,0 +1,76 @@ +// use crate::ASICamera2::BayerPattern; +// +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] +#![feature(alloc_layout_extra)] +mod asicam; + + +use crate::asicam::ASICamera2::{ControlType, ImageType}; +use crate::asicam::Camera; + +fn main() { +    operate_qhy(); +} + +fn operate_qhy() { +    println!("Operating on qhy camera ... or i'll die trying"); +} + +fn operate_asi() { +    println!("Operating on asi camera ... or i'll die trying"); +    let mut camera = asicam::acquire(0).unwrap(); + +    println!("{:?}", camera); +    camera.set_control_value(ControlType::TargetTemp, -100).unwrap(); +    camera.set_control_value(ControlType::CoolerOn, 1).unwrap(); +    std::thread::sleep(std::time::Duration::from_millis(500)); +    println!("Camera temperature is currently {:?}", camera.get_control_value(ControlType::Temperature).unwrap()); + +    /* +    for exposure in [2000, 5000, 10000, 30000].iter() { +        camera.set_control_value(ControlType::Exposure, *exposure).unwrap(); +        for gain in [450, 375, 325, 250, 200].iter() { +            camera.set_control_value(ControlType::Gain, *gain).unwrap(); +            for offset in [100, 80, 60, 40, 20, 0].iter() { +                camera.set_control_value(ControlType::Offset, *offset).unwrap(); +                take_calibration_images(&camera, 1, &format!("roof_gain_{:03}_offset_{:03}_exposure_{:06}", gain, offset, exposure)); +            } +        } +    } +    */ +    camera.set_exposure_ms(45000).unwrap(); +//    camera.set_control_value(ControlType::Exposure, 70000000).unwrap(); +    camera.set_control_value(ControlType::Gain, 350).unwrap(); +    camera.set_control_value(ControlType::Offset, 0).unwrap(); +    camera.set_control_value(ControlType::HardwareBin, 0).unwrap(); +    camera.set_roi_format(camera.width, camera.height, 1, ImageType::RGB24).unwrap(); +    take_calibration_images(&camera, 40, "dark_gain_350_exposure_45000"); +    /* +    for exposure in [1000 * 1000 * 10].iter() { +        camera.set_control_value(ControlType::Exposure, *exposure).unwrap(); +        for gain in [450, 375, 325, 250, 200].iter() { +            camera.set_control_value(ControlType::Gain, *gain).unwrap(); +            for offset in [100, 80, 70, 60, 40, 0].iter() { +                camera.set_control_value(ControlType::Offset, *offset).unwrap(); +                take_calibration_images( +                    &camera, +                    30, +                    &format!("images/gain_{:03}_offset_{:03}_exposure_{:06}", gain, offset, exposure)); +            } +        } +    } +    */ + +    println!("Done!"); +} + +fn take_calibration_images(camera: &Camera, count: u32, path_fragment: &str) { +    for i in 0..count { +        println!("{} image {:06}", path_fragment,  i); +        let temp = camera.get_control_value(ControlType::Temperature).unwrap(); +        println!("Camera temperature is currently {:?}", temp); +        camera.take_image(&format!("{}_{:06}_temp_{:03}.png", path_fragment, i, temp)).unwrap(); +    } +} | 
